如何对jwt生成的token 实现验证(已经可以验证)、过期处理以及token刷新

这是我的jwt 模块,

// 引入模块依赖
const fs = require('fs');
const path = require('path');
const jwt = require('jsonwebtoken');
// 创建 token 类
class Jwt {
    constructor(data) {
        this.data = data;
        this._id = null; // 用户自定义 存放userid
        this._date = null; // 过期时间
        this._creatDate = null; // 创建时间
    }
    // 重新生成 token
    refreshToken() {
        let data = this.data;
        let created = Math.floor(Date.now() / 1000);
        let cert = fs.readFileSync(path.join(__dirname, './pem/private_key.pem'));//私钥 可以自己生成
        let token = jwt.sign({
            data,
            exp: created + 60 * 30, // 过期时间 
            iat: created, // 创建时间
        }, cert, {algorithm: 'RS256'});
        return token;
    }
    //生成token
    generateToken(data) {
        if (data) {
            this.data = data;
        }
        let data = this.data;
        let created = Math.floor(Date.now() / 1000);
        let cert = fs.readFileSync(path.join(__dirname, './pem/private_key.pem'));//私钥 可以自己生成
        let token = jwt.sign({
            data,
            exp: created + 60 * 30, // 过期时间 30 分钟
            iat: created, // 创建时间
        }, cert, {algorithm: 'RS256'});
        return token;
    }

    // 校验token
    verifyToken(data) {
        if (data) {
            this.data = data;
        }
        let token = this.data;
        let cert = fs.readFileSync(path.join(__dirname, './pem/public_key.pem'));//公钥 可以自己生成
        let res;
        try {
            let result = jwt.verify(token, cert, {algorithms: ['RS256']}) || {};
            this._id = result.data;
            this._date = result.exp;
            this._creatDate = result.iat;
            let {exp = 0} = result, current = Math.floor(Date.now() / 1000);
            if (current <= exp) {
                res = result.data || {};
            }
        } catch (e) {
            res = 'err';
        }
        return res;
    }
}

module.exports = Jwt;

我要在 app.js 中新增一个中间件拦截请求对token进行验证正确与否,是否过期,是否需要重新生成token,是否直接返回前端重新登录,这里边是怎样的一个过程以及实现token的刷新,失效处理的方法

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
关于JWT token实现密码重置

场景:管理员创建一个用户,创建好后发送用户名和url给用户邮箱,用户点url进系统重置密码页面设置密码。token并不存在数据库中,这怎么用token实现?原先的需求是创建用户时后台随机生成密码,将用户名和密码发到用户邮箱,用户第一次登录时会强制修改密码。但今天把需求改成用token实现,就懵逼了。求大神帮助

Laravel jwt身份验证令牌已过期,token_invalid

<div class="post-text" itemprop="text"> <p>我对jwt auth令牌到期有个问题。 情况是这样的:我把laravel中的API作为一个项目来编写。 这个API使用另一个laravel项目(客户端)。 但是当我尝试用户登录,一切都很好,但之后我开始意识到TTL(60分钟)(时间生活)通过,然后当我试图让用户资源(需要登录用户)我得到json错误响应{“错误”= >“token_expired”}。 这是我使用jwt的代码的路由部分。 auth中间件:</p> <pre><code>Route::group(['middleware' =&gt; 'jwt.auth'], function () { Route::get('account/getUserDetails', 'Api\AccountController@getUserDetails'); }); </code></pre> <p>我很困惑为什么令牌不会自动刷新,我是否需要在某个地方明确指定刷新令牌的方式,难道不是这样的吗?</p> <p>“refresh_ttl”=比;20160,在jwt.php中。端点看起来是这样的:</p> <pre><code>public function getUserDetails(Request $request) { try { if (! $user = JWTAuth::parseToken()-&gt;authenticate()) { return response()-&gt;json(['user_not_found'], 404); } } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) { $refreshed = JWTAuth::refresh(JWTAuth::getToken()); $user = JWTAuth::setToken($refreshed)-&gt;toUser(); return $this-&gt;response-&gt;withArray(['token' =&gt; $refreshed]); } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) { return response()-&gt;json(['token_invalid'], $e-&gt;getStatusCode()); } catch (Tymon\JWTAuth\Exceptions\JWTException $e) { return response()-&gt;json(['token_absent'], $e-&gt;getStatusCode()); } return $user; } </code></pre> </div>

Laravel JWT Auth无法正常工作,$ token为false / true

<div class="post-text" itemprop="text"> <p>I'm using Laravel 5.7 and "tymon/jwt-auth": "1.0.0-rc.3" for authentication. After I registered an user, when i try to autenthicate him i always get a bool value: true or false, not the token. I tried all the "fixes" I found on the internet and nothing works. What am I missing?</p> <p>This is the register method:</p> <pre><code>protected function create(array $data) { if ($data['legitimation_id'][0] === 'E') { $user_type = 1; } else if ($data['legitimation_id'][0] === 'P') { $user_type = 2; } $data['user_type'] = $user_type; $data['password'] = Hash::make($data['password']); $user = User::create($data); LegitimationController::delete($data['legitimation_id']); return $user; } public function register(Request $request) { $data = $request-&gt;all(); if ($this-&gt;validator($data)-&gt;fails()) { return $this-&gt;sendError('Validation Error.', $this-&gt;validator($data)-&gt;errors()); } if (mb_substr($data['legitimation_id'], 0, 1) != 'P' &amp;&amp; mb_substr($data['legitimation_id'], 0, 1) != 'E' ) { return $this-&gt;sendError('Validation Error.', array("legitimation_id" =&gt; 'Fail')); }; $user = $this-&gt;create($data); $success = ['first_name' =&gt; $user['first_name'], 'last_name' =&gt; $user['last_name']]; return $this-&gt;sendResponse($success, 'Succes'); } </code></pre> <p>This is the login method:</p> <pre><code>public function login(Request $request) { $credentials = $request-&gt;only('email', 'password'); $jwt_token = null; if (!$jwt_token = auth('api')-&gt;attempt($credentials)) { $this-&gt;sendError("Unauthorized", ['error' =&gt; 'Invalid Email or Password'], 401); } $this-&gt;sendResponse(['token' =&gt; $jwt_token], "Succes"); } </code></pre> <p>api.php</p> <pre><code>Route::group([ 'middleware' =&gt; 'cors', 'prefix' =&gt; 'v1' ], function () { Route::post('register', 'Auth\RegisterController@register'); Route::post('login', 'Auth\LoginController@login'); }); </code></pre> <p>auth.php</p> <pre><code>'guards' =&gt; [ 'web' =&gt; [ 'driver' =&gt; 'session', 'provider' =&gt; 'users', ], 'api' =&gt; [ 'driver' =&gt; 'jwt', 'provider' =&gt; 'users', ], ], </code></pre> </div>

如何始终通过无效的密钥类型错误生成JWT令牌

<div class="post-text" itemprop="text"> <p>I met this issue and really do not know how to resolve it, can anyone help to provide a working solution?</p> <pre><code>func GenerateJWT(name, role string) (string, error) { //create a singner for rsa 256 claims := &amp;jwt.StandardClaims{ ExpiresAt: 15000, Issuer: "test", } token :=jwt.NewWithClaims(jwt.SigningMethodES256, claims) log.Println("generated toke is ") log.Println(token) tokenString, err := token.SignedString([]byte("secret")) .... } </code></pre> <p>Now I am alway having: </p> <blockquote> <p>key is of invalid type</p> </blockquote> <p>error. I google a lot, and even for <code>jwt-go</code> library it self, they are providing exactly same solution, but why I kept having the </p> <blockquote> <p>key is of invalid type</p> </blockquote> <p>error?</p> <p>Can anyone help to provide a working sample about how to generate <code>jwt</code> token in <code>go</code>?</p> </div>

关于Spring boot + SpringSecurity +jwt token失效的问题

比如我登abc的用户,然后我在另一个地点也登abc的用户,那前一个登陆的在刷新或者请求接口的时候要登出, 或者是我后台改了abc的密码,那abc这个账户在刷新请求接口的时候要登出。 框架我搭好了 代码如下: 生成token工具类: ``` public class JwtTokenUtil { private static InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("jwt.jks"); // 寻找证书文件 private static PrivateKey privateKey = null; private static PublicKey publicKey = null; static { // 将证书文件里边的私钥公钥拿出来 try { KeyStore keyStore = KeyStore.getInstance("JKS"); // java key store 固定常量 keyStore.load(inputStream, "123456".toCharArray()); privateKey = (PrivateKey) keyStore.getKey("jwt", "123456".toCharArray()); // jwt 为 命令生成整数文件时的别名 publicKey = keyStore.getCertificate("jwt").getPublicKey(); } catch (Exception e) { e.printStackTrace(); } } public static String generateToken(String subject, int expirationSeconds, String salt) { return Jwts.builder() .setClaims(null) .setSubject(subject) .setExpiration(new Date(System.currentTimeMillis() + expirationSeconds * 1000)) // .signWith(SignatureAlgorithm.HS512, salt) // 不使用公钥私钥 .signWith(SignatureAlgorithm.RS256, privateKey) .compact(); } public static String parseToken(String token, String salt) { String subject = null; try { Claims claims = Jwts.parser() // .setSigningKey(salt) // 不使用公钥私钥 .setSigningKey(publicKey) .parseClaimsJws(token).getBody(); subject = claims.getSubject(); } catch (Exception e) { } return subject; } } ``` 登陆成功后生成JTWtoken : ``` @Component public class AjaxAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { ResponseBase responseBase = new ResponseBase(); responseBase.setCode("200"); responseBase.setMassage("Login Success!"); String jwtToken = JwtTokenUtil.generateToken(String.valueOf(authentication.getPrincipal()), 300, "_secret"); responseBase.setJwtToken(jwtToken); httpServletResponse.getWriter().write(JSON.toJSONString(responseBase)); } } ``` 监听器: ``` @Component public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { @Autowired AdminSysUserSecurityService adminSysUserSecurityService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { final String authToken = authHeader.substring("Bearer ".length()); String username = JwtTokenUtil.parseToken(authToken, "_secret"); if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = adminSysUserSecurityService.loadUserByUsername(username); if (userDetails != null) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); } } } chain.doFilter(request, response); } } ``` ``` @Component("rbacauthorityservice") public class RbacAuthorityService { public boolean hasPermission(HttpServletRequest request, Authentication authentication) { Object userInfo = authentication.getPrincipal(); boolean hasPermission = false; if (userInfo instanceof UserDetails) { String username = ((UserDetails) userInfo).getUsername(); //获取资源 Set<String> urls = new HashSet(); urls.add("/**/**"); // 这些 url 都是要登录后才能访问,且其他的 url 都不能访问! Set set2 = new HashSet(); Set set3 = new HashSet(); AntPathMatcher antPathMatcher = new AntPathMatcher(); for (String url : urls) { if (antPathMatcher.match(url, request.getRequestURI())) { hasPermission = true; break; } } return hasPermission; } else { return false; } } } ``` 配置: ``` @Configuration public class AdminWebSecurityConfig extends WebSecurityConfigurerAdapter { @Value("${pay.strength}") private int strength; @Autowired private AdminSysUserSecurityService adminSysUserSecurityService; @Bean public PasswordEncoder passwordEncoder(){ // return NoOpPasswordEncoder.getInstance();//不对密码加密 return new BCryptPasswordEncoder(strength);//秘钥迭代次数为 2^strength,strength取值在 4-31 之间,默认10 } @Autowired AjaxAuthenticationEntryPoint authenticationEntryPoint; // 未登陆时返回 JSON 格式的数据给前端(否则为 html) @Autowired AjaxAuthenticationSuccessHandler authenticationSuccessHandler; // 登录成功返回的 JSON 格式数据给前端(否则为 html) @Autowired AjaxAuthenticationFailureHandler authenticationFailureHandler; // 登录失败返回的 JSON 格式数据给前端(否则为 html) @Autowired AjaxLogoutSuccessHandler logoutSuccessHandler; // 注销成功返回的 JSON 格式数据给前端(否则为 登录时的 html) @Autowired AjaxAccessDeniedHandler accessDeniedHandler; // 无权访问返回的 JSON 格式数据给前端(否则为 403 html 页面) @Autowired JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; // JWT 拦截器 @Autowired SelfAuthenticationProvider provider; // 自定义安全认证 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 加入自定义的安全认证 auth.authenticationProvider(provider); } @Override public void configure(HttpSecurity http)throws Exception{ //开启HttpSecurity配置 http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 使用 JWT,关闭token .and() .httpBasic().authenticationEntryPoint(authenticationEntryPoint) .and() .authorizeRequests() // .antMatchers("/db/**").hasRole("DB") // .antMatchers("/user/**").hasRole("USER") // .antMatchers("/admin/**").hasRole("ADMIN") // .antMatchers("/user/**").access("hasAnyRole('ADMIN','ROOT')") // .antMatchers("/db/**").access("hasAnyRole('ADMIN') and hasRole('DBA')") //除了前面路径,用户访问其他URL都必须认证后访问 .anyRequest() .access("@rbacauthorityservice.hasPermission(request,authentication)") // RBAC 动态 url 认证 .and() //开启表单登录,同事配置了登入接口为/login .formLogin() /* //该接口主要方便ajax或者移动端登入 .loginProcessingUrl("/login") //设置登录成功跳转页面,error=true控制页面错误信息的展示 .successForwardUrl("/index").failureUrl("/login?error=true") */ //登入接口都不需要认证 .successHandler(authenticationSuccessHandler) // 登录成功 .failureHandler(authenticationFailureHandler) // 登录失败 .permitAll() .and() //开启注销登入配置 .logout() .logoutSuccessHandler(logoutSuccessHandler) .permitAll(); http.rememberMe().rememberMeParameter("remember-me") .userDetailsService(adminSysUserSecurityService).tokenValiditySeconds(300); http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 无权访问 JSON 格式的数据 http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // JWT Filter } ``` 登陆成功后获取token,postman测试: ![图片说明](https://img-ask.csdn.net/upload/201912/11/1576056718_177252.png) 可以 但是我重新调用新的登陆接口,相同用户名获取新的token后,原来的token依旧可以请求。 所以要在哪边配置 用户其它地方登陆,或者用户密码变更,jtwtoken失效

JWT签名验证失败,java到php

<div class="post-text" itemprop="text"> <p>I share with you the first codes</p> <p>php codes <a href="http://pastebin.com/b8TNfyzq" rel="nofollow">http://pastebin.com/b8TNfyzq</a> line 22</p> <p>JwtTester.java <a href="http://pastebin.com/TsF0wsCX" rel="nofollow">http://pastebin.com/TsF0wsCX</a> line 22</p> <p>Token created in java code I wrote in php server does not match the token. Although I can not verify the same key on both sides</p> <p>I'm using github.com/jwtk/jjwt in java code and github.com/firebase/php-jwt in php codes</p> <p>same with java code and data in key , consists of different token when I create the token in only PHP</p> </div>

如何验证JWT签名?

<div class="post-text" itemprop="text"> <p>I want to authenticate Android users with a Go AppEngine backend,</p> <p>I can easily get an ID-token in Android by following <a href="http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html" rel="nofollow">http://android-developers.blogspot.co.il/2013/01/verifying-back-end-calls-from-android.html</a></p> <p>the ID-token payload can be verified with the oauth2/v2 package of the <a href="https://code.google.com/p/google-api-go-client/" rel="nofollow">https://code.google.com/p/google-api-go-client/</a> library.</p> <p>some installation tweaks are necessary for using it with AppEngine, I found some pointers at <a href="http://golangtutorials.blogspot.co.il/2011/11/using-external-api-in-go-appengine.html" rel="nofollow">http://golangtutorials.blogspot.co.il/2011/11/using-external-api-in-go-appengine.html</a></p> <p>according to the doc: "Verify Signature It turns out that this is signed using a Google public/private key pair, and Google publishes the public keys (which we change regularly) at www.googleapis.com/oauth2/v1/certs; go ahead and have a look.</p> <p>You have to verify that the ID Token, which is actually a JSON Web Token, was signed with one of those certs. Fortunately, there are decent libraries around to do this; in this post, I’ll give pointers for Java, Ruby, and PHP.</p> <p>The libraries can cache the Google certs and only refresh them when required, so the verification is (almost always) a fast static call."</p> <p>how do I verify in Go that the token was signed by Google?</p> </div>

Android中如何用Token实现自动登录

我想用token实现自动登录的功能,这样就不用每次进来登录一遍了。

各位大神,请问些公开部分API关于Token验证的问题

是个JavaWeb项目,现在想公开部分API给app端的开发者调用,想在调用API前加个Token验证,但是实现起来有点困惑,请各位大神赐教。 我的问题大概如下: 1.用户登录成功后分配一个Token给他 -Token怎样写?(现在思路是根据URL和请求参数生成,并以Json格式传回给用户) -以怎样的方式分配给用户? -用户的Token打算存在内存还是数据库?用户的Token存在哪里?服务器的Token存在哪里? 2.用户每次使用API都验证他的Token和用户名,若吻合则允许访问该API,否则显示警告“令牌失效” -用户调用api时以什么方式将token传给服务器?

jwt登录过期的问题求大佬指教

问题一:jwt.expiration 是设置token过期时间吧? 问题二:token是不是保存在浏览器中 因为我用谷歌登录之后不能登录了 我换了个浏览器又可以登录了? 什么情况

(Golang)JWT签名验证问题

<div class="post-text" itemprop="text"> <p>I'm trying to get my head around JWT tokens in Golang. I'm using <a href="http://github.com/dgrijalva/jwt-go" rel="nofollow">github.com/dgrijalva/jwt-go</a>. </p> <p>What caught me off guard is the fact that I can enter multiple valid signatures.</p> <p>For example, head over to <a href="http://jwt.io" rel="nofollow">http://jwt.io</a> - enter MySuperSecretKey for the secret</p> <p>This token is valid:</p> <p>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NTc3MzAyODMsInVzZXIiOiJ1c2VyMSJ9.SxshVL42DUH9e7jXUblbB_bTwKxhe4jo70DrvbQMlaU</p> <p>as well as this one:</p> <p>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NTc3MzAyODMsInVzZXIiOiJ1c2VyMSJ9.SxshVL42DUH9e7jXUblbB_bTwKxhe4jo70DrvbQMlaV</p> <p>In fact, if I change the last letter to V, W or X, I get a "Signature Verfied" message.</p> <p>Can anyone tell me what's going on here? </p> </div>

与公钥和私钥以及JWT相关的混乱

<div class="post-text" itemprop="text"> <p>I'm trying out JWT (JSON Web Tokens) in a Go web service. Here's what I've done so far:</p> <pre><code>package jwt import( "fmt" "net/http" "github.com/gorilla/mux" "github.com/dgrijalva/jwt-go" "io/ioutil" ) var privateKey []byte var publicKey []byte func JSONWebTokensHandler(w http.ResponseWriter, r * http.Request){ // Create the token encodeToken := jwt.New(jwt.SigningMethodHS256) // Set some claims encodeToken.Claims["Latitude"] = "25.000" encodeToken.Claims["Longitude"] = "27.000" // Sign and get the complete encoded token as a string tokenString, err := encodeToken.SignedString(privateKey) decodeToken, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) } return publicKey,nil }) if decodeToken.Valid { fmt.Fprintf(w,"Lat: %s, Lng: %s",decodeToken.Claims["Latitude"],decodeToken.Claims["Longitude"]) } else { fmt.Fprintf(w,"Couldn't handle this token: %s", err) } } func init(){ privateKey,_ = ioutil.ReadFile("demo.rsa") publicKey,_ = ioutil.ReadFile("demo.rsa.pub") r := mux.NewRouter() r.HandleFunc("/jwt",JSONWebTokensHandler).Methods("GET") http.Handle("/", r) } </code></pre> <p>Now if my understanding is correct, A token that is encoded using a private key can be decoded using the public key. That is what I've presumed in the code above however when I run the code I get the error:</p> <blockquote> <p>Couldn't handle this token: signature is invalid</p> </blockquote> <p>If I use the same key for encoding and decoding, then the code works.</p> <p>What I'd like to know is, is there something wrong with my understanding or in the code? </p> </div>

在jwt-go中解析JWT Auth令牌时,密钥的类型无效

<div class="post-text" itemprop="text"> <p>I am setting up security middleware in a GoLang API and seem to have everything set up correctly, but I am getting an error ‘key is of invalid type’. </p> <p>I have confirmed that my Signing algorithm is RS256 and the middleware options are configured @ SigningMethod: jwt.SigningMethodRS256</p> <p>I have a valid token…everything else in the middleware passes. </p> <p>The entry point to this error in the middleware is the jwt.ParseRSAPrivateKeyFromPEM method. </p> <p>I’ve isolated the error down inside the package github.com/dgrijalva/jwt-go/rsa.go Verify() on line :62 is the ErrInvalidKeyType that is getting thrown. All the params up to the this point seem solid and appropriate (eg m|signingString|signature|key) but this key.(*rsa.PublicKey) is failing…in my debugger (GoLand) I inspect *rsa and am given the response ‘could not find symbol value for rsa’…</p> <pre><code>if rsaKey, ok = key.(*rsa.PublicKey); !ok { return ErrInvalidKeyType } </code></pre> <p>please note…if it’s not already too obvious…i’m noob to GoLang</p> <p>----- UPDATE -----</p> <p>So at the most granular level the panic starts at go/1.12.8/libexec/src/crypto/rsa/rsa.go:49 with </p> <pre><code>func (pub *PublicKey) Size() int { log.Printf("SIZE ::: %v :: %v",pub.N.BitLen(), pub.N) return (pub.N.BitLen() + 7) / 8 } </code></pre> <p>The pub is seen as a nil pointer dereference. I trace it back to mux --&gt;</p> <blockquote> <p>crypto/rsa.VerifyPKCS1v15(...) /usr/local/Cellar/go/1.12.8/libexec/src/crypto/rsa/pkcs1v15.go:275</p> <p>github.com/dgrijalva/jwt-go.(*SigningMethodRSA).Verify(...) /Users/me/Sandbox/src/github.com/dgrijalva/jwt-go/rsa.go:73</p> <p>github.com/dgrijalva/jwt-go.(*Parser).ParseWithClaims(...) /Users/me/Sandbox/src/github.com/dgrijalva/jwt-go/parser.go:77</p> <p>github.com/dgrijalva/jwt-go.(*Parser).Parse(...) /Users/btschirhart/Sandbox/src/github.com/dgrijalva/jwt-go/parser.go:20</p> <p>github.com/dgrijalva/jwt-go.Parse(...) /Users/me/Sandbox/src/github.com/dgrijalva/jwt-go/token.go:89</p> <p>github.com/auth0/go-jwt-middleware.(*JWTMiddleware).CheckJWT(...) /Users/me/Sandbox/src/github.com/auth0/go-jwt-middleware/jwtmiddleware.go:203</p> <p>github.com/auth0/go-jwt-middleware.(*JWTMiddleware).Handler.func1(...) /Users/me/Sandbox/src/github.com/auth0/go-jwt-middleware/jwtmiddleware.go:110</p> <p>net/http.HandlerFunc.ServeHTTP(...) /usr/local/Cellar/go/1.12.8/libexec/src/net/http/server.go:1995</p> <p>github.com/gorilla/mux.(*Router).ServeHTTP(...) /Users/me/Sandbox/src/github.com/gorilla/mux/mux.go:210 +0xe3</p> </blockquote> </div>

springcloud oauth2.0 jwt 前后端分离的几个问题

oauth2.0提供了一种客户端模式获取token的方式,A微服务就可以用feign通过这种模式请求B服务的相关接口。(zuul,eureka) 第一个问题: 是否有这样一种场景,前端调用A服务的某接口,而这个接口需要调用B服务的某接口,但是这个接口需要用户有一定角色权限才可调用,前端登录的用户是有这种角色权限的,但是由于A服务调用B服务是通过客户端模式生成的token和用户是没关系的,所以会因为没权限调用不了?A服务调用B服务是都通过客户端模式生成token去调用还是会判断前端是否传token,有的话把前端传过来的token继续传过去呢? 第二个问题: 而假设现在不是由前端调用,而是A服务有个定时器,需要调用B服务查询数据的一个接口,而B服务的这个接口是不应该让前端可以调用到。如果正常写接口的话,用户应该还是可以通过zuul到eureka调用到这个接口的吧?这时怎么限制这个不让前端进行调用?修改zuul匹配规则只能请求某路径开头的接口?还是别的怎么方式? 第三个问题: 我github上看了一个基于jwt的前后端分离的oauth2.0的单点登录项目,前端nodejs+vue,然后登录的时候是自定义实现的,用户名+密码+clientid+clientsecret获取token,然后后面可以用refreshtoken + clientid + clientsecret调用接口/oauth/token 续期token。而由于他这里是直接在js里面发起请求到zuul层,所以clientid和clientsecret是直接暴露在js里面的,然后上面说了有一种客户端模式获取token,就是只需要clientid+clientsecret就可以拿到token,只是不能refresh。这样的话把clientid和clientsecret直接写在js里面暴露出来靠谱吗? 而登录已经需要用户名密码了为什么还让传clientid和clientsecret。有什么意义吗?传clientid能理解,clientid有一个scope,但感觉好像没必要也要传clientsecret

微服务架构中的网关只做鉴权而不做JWT解析用户信息,鉴权通过由调用的微服务来做JWT解析拿到用户信息,为什么不可以让网关做鉴权并解析用户信息后发送给各个微服务?

5.2 结合RSA的鉴权 流程图: ![图片说明](https://img-ask.csdn.net/upload/202003/10/1583813913_921894.png) 我们首先利用RSA生成公钥和私钥。私钥保存在授权中心,公钥保存在Zuul和各个微服务 1. 用户请求登录 1. 授权中心校验,通过后用私钥对JWT进行签名加密 1. 返回JWT给用户 1. 用户携带JWT访问 1. Zuul直接通过公钥解密JWT,进行验证,验证通过则放行 1. 请求到达微服务,微服务直接用公钥解析JWT,获取用户信息,无需访问授权中心

使用PHP和JWT验证在Javascript中生成的Firebase令牌

<div class="post-text" itemprop="text"> <p>Working on a web app in JavaScript using Firebase authentication that needs to reach out to a remote PHP script.</p> <p>The user should be able to log into the web app, then once authenticated has access to the functionality of the PHP script.</p> <p>I generated a token with <code>firebase.auth().currentUser.getToken()</code> and successfully POSTed to the PHP server. </p> <pre><code> firebase.auth().currentUser.getToken(true).then(function(idToken) { var uid = firebase.auth().currentUser.uid; var http = new XMLHttpRequest(); var url = "http://localhost/json.php"; var params = "token=" + idToken + "&amp;uid=" + uid; http.open("POST", url, true); //Send the proper header information along with the request http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http.onreadystatechange = function() {//Call a function when the state changes. if(http.readyState == 4 &amp;&amp; http.status == 200) { alert(http.responseText); } } http.send(params); //console.log("TOKEN: " + idToken); }).catch(function(error) { // Handle error }); </code></pre> <p>However, I'm having some issue on the PHP side where all I need is to validate that the user is currently signed in. I tried the firebase/php-jwt library but I seem to be missing how to do a simple validation so the user can unlock the functionality of the PHP script.</p> <p>Any ideas?</p> </div>

Laravel 5.7更改默认的auth表

<div class="post-text" itemprop="text"> <p>i'm a real laravel noob as i was obliged to work with it for my uni project, i've been trying for 5 hours now to make authentification work on my project with no avail, i've been trying to switch the default auth table from users with utilisateurs (my custom db table), it has all prerequisites yet whenever i click on the login button it just refreshes the login page, a side note i'm not trying to use register form as in the context of my project, only a utilisateur is able to add another utilisateur, my custom db table "utilisateur" has the following rows (idutilisateur,pseudo,mdp,telephone,usertype,bloque,remember_token,created_at,updated_at)</p> <p>this is my LoginController</p> <pre><code>&lt;?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\AuthenticatesUsers; class LoginController extends Controller { /* |-------------------------------------------------------------------------- | Login Controller |-------------------------------------------------------------------------- | | This controller handles authenticating users for the application and | redirecting them to your home screen. The controller uses a trait | to conveniently provide its functionality to your applications. | */ use AuthenticatesUsers; /** * Where to redirect users after login. * * @var string */ protected $redirectTo = '/utilisateurs'; /** * Create a new controller instance. * * @return void */ public function __construct() { $this-&gt;middleware('guest')-&gt;except('logout'); } public function authenticate(Request $request) { $credentials = $request-&gt;only('pseudo', 'mdp'); if (Auth::attempt($credentials)) { // Authentication passed... return redirect()-&gt;intended('utilisateurs'); } } } </code></pre> <p>This is login.blade.php</p> <pre><code>@extends('layouts.app') @section('content') &lt;div class="container"&gt; &lt;div class="row justify-content-center"&gt; &lt;div class="col-md-8"&gt; &lt;div class="card"&gt; &lt;div class="card-header"&gt;{{ __('Login') }}&lt;/div&gt; &lt;div class="card-body"&gt; &lt;form method="POST" action="{{ route('login') }}"&gt; @csrf &lt;div class="form-group row"&gt; &lt;label for="text" class="col-md-4 col-form-label text-md-right"&gt;{{ __('Pseudo') }}&lt;/label&gt; &lt;div class="col-md-6"&gt; &lt;input id="pseudo" type="text" class="form-control{{ $errors-&gt;has('pseudo') ? ' is-invalid' : '' }}" name="pseudo" value="{{ old('pseudo') }}" required autofocus&gt; @if ($errors-&gt;has('pseudo')) &lt;span class="invalid-feedback" role="alert"&gt; &lt;strong&gt;{{ $errors-&gt;first('pseudo') }}&lt;/strong&gt; &lt;/span&gt; @endif &lt;/div&gt; &lt;/div&gt; &lt;div class="form-group row"&gt; &lt;label for="password" class="col-md-4 col-form-label text-md-right"&gt;{{ __('Mot de passe') }}&lt;/label&gt; &lt;div class="col-md-6"&gt; &lt;input id="mdp" type="password" class="form-control{{ $errors-&gt;has('mdp') ? ' is-invalid' : '' }}" name="mdp" required&gt; @if ($errors-&gt;has('mdp')) &lt;span class="invalid-feedback" role="alert"&gt; &lt;strong&gt;{{ $errors-&gt;first('mdp') }}&lt;/strong&gt; &lt;/span&gt; @endif &lt;/div&gt; &lt;/div&gt; &lt;div class="form-group row"&gt; &lt;div class="col-md-6 offset-md-4"&gt; &lt;div class="form-check"&gt; &lt;input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}&gt; &lt;label class="form-check-label" for="remember"&gt; {{ __('Remember Me') }} &lt;/label&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="form-group row mb-0"&gt; &lt;div class="col-md-8 offset-md-4"&gt; &lt;button type="submit" class="btn btn-primary"&gt; {{ __('Login') }} &lt;/button&gt; @if (Route::has('password.request')) &lt;a class="btn btn-link" href="{{ route('password.request') }}"&gt; {{ __('Forgot Your Password?') }} &lt;/a&gt; @endif &lt;/div&gt; &lt;/div&gt; &lt;/form&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; @endsection </code></pre> <p>this is auth.php</p> <pre><code>&lt;?php return [ /* |-------------------------------------------------------------------------- | Authentication Defaults |-------------------------------------------------------------------------- | | This option controls the default authentication "guard" and password | reset options for your application. You may change these defaults | as required, but they're a perfect start for most applications. | */ 'defaults' =&gt; [ 'guard' =&gt; 'web', 'passwords' =&gt; 'utilisateurs', ], /* |-------------------------------------------------------------------------- | Authentication Guards |-------------------------------------------------------------------------- | | Next, you may define every authentication guard for your application. | Of course, a great default configuration has been defined for you | here which uses session storage and the Eloquent user provider. | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | Supported: "session", "token" | */ 'guards' =&gt; [ 'web' =&gt; [ 'driver' =&gt; 'session', 'provider' =&gt; 'utilisateurs', ], 'api' =&gt; [ 'driver' =&gt; 'token', 'provider' =&gt; 'users', ], ], /* |-------------------------------------------------------------------------- | User Providers |-------------------------------------------------------------------------- | | All authentication drivers have a user provider. This defines how the | users are actually retrieved out of your database or other storage | mechanisms used by this application to persist your user's data. | | If you have multiple user tables or models you may configure multiple | sources which represent each model / table. These sources may then | be assigned to any extra authentication guards you have defined. | | Supported: "database", "eloquent" | */ 'providers' =&gt; [ 'utilisateurs' =&gt; [ 'driver' =&gt; 'eloquent', 'model' =&gt; App\Utilisateur::class, ], // 'users' =&gt; [ // 'driver' =&gt; 'database', // 'table' =&gt; 'users', // ], ], /* |-------------------------------------------------------------------------- | Resetting Passwords |-------------------------------------------------------------------------- | | You may specify multiple password reset configurations if you have more | than one user table or model in the application and you want to have | separate password reset settings based on the specific user types. | | The expire time is the number of minutes that the reset token should be | considered valid. This security feature keeps tokens short-lived so | they have less time to be guessed. You may change this as needed. | */ 'passwords' =&gt; [ 'utilisateurs' =&gt; [ 'provider' =&gt; 'utilisateurs', 'table' =&gt; 'password_resets', 'expire' =&gt; 60, ], ], ]; </code></pre> <p>I really hope you people would help me i'll be really grateful. Thanks in advance</p> </div>

shiro登录及session疑问?

1、shiro认证登录时,先走自定义的realm,再走的登录方法,在登录方法中会再次跳回realm,这是可能是哪里的问题导致的?? 2、看到网上很多人说,当用户登录成功后,shiro会把用户名放到session的attribute中,key为DefaultSubjectContext_PRINCIPALS_SESSION_KEY,但是我的session中怎么没有attribute,取不到这个值?? 3、我重写了AdviceFilter方法,用来记录日志,自定的filter在shiro.xml中怎么配置?? 求大神赐教!!

技术大佬:我去,你写的 switch 语句也太老土了吧

昨天早上通过远程的方式 review 了两名新来同事的代码,大部分代码都写得很漂亮,严谨的同时注释也很到位,这令我非常满意。但当我看到他们当中有一个人写的 switch 语句时,还是忍不住破口大骂:“我擦,小王,你丫写的 switch 语句也太老土了吧!” 来看看小王写的代码吧,看完不要骂我装逼啊。 private static String createPlayer(PlayerTypes p...

Vue + Spring Boot 项目实战(十九):Web 项目优化解决方案

快来一起探索如何打脸我们的破项目,兄弟姐妹们把害怕打在公屏上!

你连存活到JDK8中著名的Bug都不知道,我怎么敢给你加薪

CopyOnWriteArrayList.java和ArrayList.java,这2个类的构造函数,注释中有一句话 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public ArrayList(Collection&lt;? ...

副业收入是我做程序媛的3倍,工作外的B面人生是怎样的?

提到“程序员”,多数人脑海里首先想到的大约是:为人木讷、薪水超高、工作枯燥…… 然而,当离开工作岗位,撕去层层标签,脱下“程序员”这身外套,有的人生动又有趣,马上展现出了完全不同的A/B面人生! 不论是简单的爱好,还是正经的副业,他们都干得同样出色。偶尔,还能和程序员的特质结合,产生奇妙的“化学反应”。 @Charlotte:平日素颜示人,周末美妆博主 大家都以为程序媛也个个不修边幅,但我们也许...

CSDN:因博主近期注重写专栏文章(已超过150篇),订阅博主专栏人数在突增,近期很有可能提高专栏价格(已订阅的不受影响),提前声明,敬请理解!

CSDN:因博主近期注重写专栏文章(已超过150篇),订阅博主专栏人数在突增,近期很有可能提高专栏价格(已订阅的不受影响),提前声明,敬请理解! 目录 博客声明 大数据了解博主粉丝 博主的粉丝群体画像 粉丝群体性别比例、年龄分布 粉丝群体学历分布、职业分布、行业分布 国内、国外粉丝群体地域分布 博主的近期访问每日增量、粉丝每日增量 博客声明 因近期博主写专栏的文章越来越多,也越来越精细,逐步优化文章。因此,最近一段时间,订阅博主专栏的人数增长也非常快,并且专栏价

一个HashMap跟面试官扯了半个小时

一个HashMap能跟面试官扯上半个小时 关注 安琪拉的博客 1.回复面试领取面试资料 2.回复书籍领取技术电子书 3.回复交流领取技术电子书 前言 HashMap应该算是Java后端工程师面试的必问题,因为其中的知识点太多,很适合用来考察面试者的Java基础。 开场 面试官: 你先自我介绍一下吧! 安琪拉: 我是安琪拉,草丛三婊之一,最强中单(钟馗不服)!哦,不对,串场了,我是**,目...

我说我不会算法,阿里把我挂了。

不说了,字节跳动也反手把我挂了。

记录下入职中软一个月(外包华为)

我在年前从上一家公司离职,没想到过年期间疫情爆发,我也被困在家里,在家呆着的日子让人很焦躁,于是我疯狂的投简历,看面试题,希望可以进大公司去看看。 我也有幸面试了我觉得还挺大的公司的(虽然不是bat之类的大厂,但是作为一名二本计算机专业刚毕业的大学生bat那些大厂我连投简历的勇气都没有),最后选择了中软,我知道这是一家外包公司,待遇各方面甚至不如我的上一家公司,但是对我而言这可是外包华为,能...

面试:第十六章:Java中级开发

HashMap底层实现原理,红黑树,B+树,B树的结构原理 Spring的AOP和IOC是什么?它们常见的使用场景有哪些?Spring事务,事务的属性,传播行为,数据库隔离级别 Spring和SpringMVC,MyBatis以及SpringBoot的注解分别有哪些?SpringMVC的工作原理,SpringBoot框架的优点,MyBatis框架的优点 SpringCould组件有哪些,他们...

培训班出来的人后来都怎么样了?(二)

接着上回说,培训班学习生涯结束了。后面每天就是无休止的背面试题,不是没有头脑的背,培训公司还是有方法的,现在回想当时背的面试题好像都用上了,也被问到了。回头找找面试题,当时都是打印下来天天看,天天背。 不理解呢也要背,面试造飞机,上班拧螺丝。班里的同学开始四处投简历面试了,很快就有面试成功的,刚开始一个,然后越来越多。不知道是什么原因,尝到胜利果实的童鞋,不满足于自己通过的公司,嫌薪水要少了,选择...

面试了一个 31 岁程序员,让我有所触动,30岁以上的程序员该何去何从?

最近面试了一个31岁8年经验的程序猿,让我有点感慨,大龄程序猿该何去何从。

大三实习生,字节跳动面经分享,已拿Offer

说实话,自己的算法,我一个不会,太难了吧

程序员垃圾简历长什么样?

已经连续五年参加大厂校招、社招的技术面试工作,简历看的不下于万份 这篇文章会用实例告诉你,什么是差的程序员简历! 疫情快要结束了,各个公司也都开始春招了,作为即将红遍大江南北的新晋UP主,那当然要为小伙伴们做点事(手动狗头)。 就在公众号里公开征简历,义务帮大家看,并一一点评。《启舰:春招在即,义务帮大家看看简历吧》 一石激起千层浪,三天收到两百多封简历。 花光了两个星期的所有空闲时...

工作八年,月薪60K,裸辞两个月,投简历投到怀疑人生!

近日,有网友在某职场社交平台吐槽,自己裸辞两个月了,但是找工作却让自己的心态都要崩溃了,全部无果,不是已查看无回音,就是已查看不符合。 “工作八年,两年一跳,裸辞两个月了,之前月薪60K,最近找工作找的心态崩了!所有招聘工具都用了,全部无果,不是已查看无回音,就是已查看不符合。进头条,滴滴之类的大厂很难吗???!!!投简历投的开始怀疑人生了!希望 可以收到大厂offer” 先来看看网...

大牛都会用的IDEA调试技巧!!!

导读 前天面试了一个985高校的实习生,问了他平时用什么开发工具,他想也没想的说IDEA,于是我抛砖引玉的问了一下IDEA的调试用过吧,你说说怎么设置断点...

都前后端分离了,咱就别做页面跳转了!统统 JSON 交互

文章目录1. 无状态登录1.1 什么是有状态1.2 什么是无状态1.3 如何实现无状态1.4 各自优缺点2. 登录交互2.1 前后端分离的数据交互2.2 登录成功2.3 登录失败3. 未认证处理方案4. 注销登录 这是本系列的第四篇,有小伙伴找不到之前文章,松哥给大家列一个索引出来: 挖一个大坑,Spring Security 开搞! 松哥手把手带你入门 Spring Security,别再问密...

97年世界黑客编程大赛冠军作品(大小仅为16KB),惊艳世界的编程巨作

这是世界编程大赛第一名作品(97年Mekka ’97 4K Intro比赛)汇编语言所写。 整个文件只有4095个字节, 大小仅仅为16KB! 不仅实现了3D动画的效果!还有一段震撼人心的背景音乐!!! 内容无法以言语形容,实在太强大! 下面是代码,具体操作看最后! @echo off more +1 %~s0|debug e100 33 f6 bf 0 20 b5 10 f3 a5...

程序员是做全栈工程师好?还是专注一个领域好?

昨天,有位大一的同学私信我,说他要做全栈工程师。 我一听,这不害了孩子么,必须制止啊。 谁知,讲到最后,更确定了他做全栈程序员的梦想。 但凡做全栈工程师的,要么很惨,要么很牛! 但凡很牛的,绝不是一开始就是做全栈的! 全栈工程师听起来好听,但绝没有你想象的那么简单。 今天听我来给你唠,记得帮我点赞哦。 一、全栈工程师的职责 如果你学习编程的目的只是玩玩,那随意,想怎么学怎么学。...

不要再到处使用 === 了

我们知道现在的开发人员都使用 === 来代替 ==,为什么呢?我在网上看到的大多数教程都认为,要预测 JavaScript 强制转换是如何工作这太复杂了,因此建议总是使用===。这些都...

什么是a站、b站、c站、d站、e站、f站、g站、h站、i站、j站、k站、l站、m站、n站?00后的世界我不懂!

A站 AcFun弹幕视频网,简称“A站”,成立于2007年6月,取意于Anime Comic Fun,是中国大陆第一家弹幕视频网站。A站以视频为载体,逐步发展出基于原生内容二次创作的完整生态,拥有高质量互动弹幕,是中国弹幕文化的发源地;拥有大量超粘性的用户群体,产生输出了金坷垃、鬼畜全明星、我的滑板鞋、小苹果等大量网络流行文化,也是中国二次元文化的发源地。 B站 全称“哔哩哔哩(bilibili...

十个摸鱼,哦,不对,是炫酷(可以玩一整天)的网站!!!

文章目录前言正文**1、Kaspersky Cyberthreat real-time map****2、Finding Home****3、Silk – Interactive Generative Art****4、Liquid Particles 3D****5、WINDOWS93****6、Staggering Beauty****7、Ostagram图片生成器网址****8、全历史网址*...

终于,月薪过5万了!

来看几个问题想不想月薪超过5万?想不想进入公司架构组?想不想成为项目组的负责人?想不想成为spring的高手,超越99%的对手?那么本文内容是你必须要掌握的。本文主要详解bean的生命...

用了这个 IDE 插件,5分钟解决前后端联调!

点击上方蓝色“程序猿DD”,选择“设为星标”回复“资源”获取独家整理的学习资料!作者 |李海庆我是一个 Web 开发前端工程师,受到疫情影响,今天是我在家办公的第78天。开发了两周,...

大厂的 404 页面都长啥样?最后一个笑了...

每天浏览各大网站,难免会碰到404页面啊。你注意过404页面么?猿妹搜罗来了下面这些知名网站的404页面,以供大家欣赏,看看哪个网站更有创意: 正在上传…重新上传取消 腾讯 正在上传…重新上传取消 网易 淘宝 百度 新浪微博 正在上传…重新上传取消 新浪 京东 优酷 腾讯视频 搜...

自从喜欢上了B站这12个UP主,我越来越觉得自己是个废柴了!

不怕告诉你,我自从喜欢上了这12个UP主,哔哩哔哩成为了我手机上最耗电的软件,几乎每天都会看,可是吧,看的越多,我就越觉得自己是个废柴,唉,老天不公啊,不信你看看…… 间接性踌躇满志,持续性混吃等死,都是因为你们……但是,自己的学习力在慢慢变强,这是不容忽视的,推荐给你们! 都说B站是个宝,可是有人不会挖啊,没事,今天咱挖好的送你一箩筐,首先啊,我在B站上最喜欢看这个家伙的视频了,为啥 ,咱撇...

代码注释如此沙雕,会玩还是你们程序员!

某站后端代码被“开源”,同时刷遍全网的,还有代码里的那些神注释。 我们这才知道,原来程序员个个都是段子手;这么多年来,我们也走过了他们的无数套路… 首先,产品经理,是永远永远吐槽不完的!网友的评论也非常扎心,说看这些代码就像在阅读程序员的日记,每一页都写满了对产品经理的恨。 然后,也要发出直击灵魂的质问:你是尊贵的付费大会员吗? 这不禁让人想起之前某音乐app的穷逼Vip,果然,穷逼在哪里都是...

Java14 新特性解读

Java14 已于 2020 年 3 月 17 号发布,官方特性解读在这里:https://openjdk.java.net/projects/jdk/14/以下是个人对于特性的中文式...

前端还能这么玩?(女朋友生日,用前端写了一个好玩的送给了她,高兴坏了)

前端还能这么玩?(女朋友生日,用前端写了一个好玩的送给了她,高兴坏了)

爬虫(101)爬点重口味的

小弟最近在学校无聊的很哪,浏览网页突然看到一张图片,都快流鼻血。。。然后小弟冥思苦想,得干一点有趣的事情python 爬虫库安装https://s.taobao.com/api?_ks...

工作两年简历写成这样,谁要你呀!

作者:小傅哥 博客:https://bugstack.cn 沉淀、分享、成长,让自己和他人都能有所收获! 一、前言 最近有伙伴问小傅哥,我的简历怎么投递了都没有反应,心里慌的很呀。 工作两年了目前的公司没有什么大项目,整天的维护别人的代码,有坑也不让重构,都烦死了。荒废我一身技能无处施展,投递的简历也没人看。我是不动物园里的猩猩,狒狒了! 我要加班,我要996,我要疯狂编码,求给我个机会… ...

正点原子:STM32F103(战舰)、STM32F407(探索者)、STM32F103(MINI)原理图和PCB

正点原子:STM32F103(战舰)、STM32F407(探索者)、STM32F103(MINI)原理图和PCB

相关热词 c# 解析cad c#数字格式化万 c#int转byte c#格式化日期 c# wpf 表格 c# 实现ad域验证登录 c#心跳包机制 c#使用fmod.dll c#dll vb 调用 c# outlook
立即提问
相关内容推荐