先介绍下利用 JWT 进行鉴权的思路:
1, 用户发起登录请求.
2, 服务端创建一个加密后的 JWT 信息, 作为 Token 返回.
3, 在后续请求中 JWT 信息作为请求头, 发给服务端.
4, 服务端拿到 JWT 之后进行解密, 正确解密表示此次请求合法, 验证通过; 解密失败说明 Token 无效或者已过期.
流程图如下:
网图
一, 用户发起登录请求
欢迎大家访问 www.fota.com
二, 服务端创建一个加密后的 JWT 信息, 作为 Token 返回
1, 用户登录之后把生成的 Token 返回给前端
- @Authorization
- @ResponseBody
- @GetMapping("user/info/auth")
- public Result getUserSecurityInfo(HttpServletRequest request) {
- try {
- UserDTO userDTO = ...
- UserVO userVO = new UserVO();
- // 这里调用创建 JWT 信息的方法
- userVO.setToken(TokenUtil.createJWT(String.valueOf(userDTO.getId())));
- return Result.success(userVO);
- } catch (Exception e) {
- return Result.fail(ErrorEnum.SYSTEM_ERROR);
- }
- }
2, 创建 JWT,Generate Tokens
- import javax.crypto.spec.SecretKeySpec;
- import javax.xml.bind.DatatypeConverter;
- import java.security.Key;
- import io.jsonwebtoken.*;
- import java.util.Date;
- //Sample method to construct a JWT
- private String createJWT(String id, String issuer, String subject, long ttlMillis) {
- //The JWT signature algorithm we will be using to sign the token
- SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
- long nowMillis = System.currentTimeMillis();
- Date now = new Date(nowMillis);
- //We will sign our JWT with our ApiKey secret
- byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(apiKey.getSecret());
- Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
- //Let's set the JWT Claims
- JwtBuilder builder = Jwts.builder().setId(id)
- .setIssuedAt(now)
- .setSubject(subject)
- .setIssuer(issuer)
- .signWith(signatureAlgorithm, signingKey);
- //if it has been specified, let's add the expiration
- if (ttlMillis>= 0) {
- long expMillis = nowMillis + ttlMillis;
- Date exp = new Date(expMillis);
- builder.setExpiration(exp);
- }
- //Builds the JWT and serializes it to a compact, URL-safe string
- return builder.compact();
- }
3, 作为 Token 返回
看后面有个 Token
三, 在后续请求中 JWT 信息作为请求头, 发给服务端
缺一个图, 马上补
四, 服务端拿到 JWT 之后进行解密, 正确解密表示此次请求合法, 验证通过; 解密失败说明 Token 无效或者已过期.
1, 在拦截器中读取这个 Header 里面的 Token 值
- @Slf4j
- @Component
- public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
- private boolean chechToken(HttpServletRequest request, HttpServletResponse response) throws IOException{
- Long userId = ...;
- if (!TokenUtil.parseJWT(request.getHeader("Authorization"), String.valueOf(userId))){
- response.setContentType("text/html;charset=GBK");
- response.setCharacterEncoding("GBK");
- response.setStatus(403);
- response.getWriter().print("<font size=6 color=red > 对不起, 您的请求非法, 系统拒绝响应!</font>");
- return false;
- } else{
- return true;
- }
- }
- }
2, 拿到之后进行解密校验
- Decode and Verify Tokens
- import javax.xml.bind.DatatypeConverter;
- import io.jsonwebtoken.Jwts;
- import io.jsonwebtoken.Claims;
- //Sample method to validate and read the JWT
- private void parseJWT(String jwt) {
- //This line will throw an exception if it is not a signed JWS (as expected)
- Claims claims = Jwts.parser()
- .setSigningKey(DatatypeConverter.parseBase64Binary(apiKey.getSecret()))
- .parseClaimsJws(jwt).getBody();
- System.out.println("ID:" + claims.getId());
- System.out.println("Subject:" + claims.getSubject());
- System.out.println("Issuer:" + claims.getIssuer());
- System.out.println("Expiration:" + claims.getExpiration());
- }
五, 总结
大家知道, 我之前做过爬虫, 实际这种思路在微博做反爬时也用过, 做过我之前文章的同学应该知道.
来源: http://www.jianshu.com/p/68779236aa23