Home > Java > javaTutorial > How does Spring Boot integrate JWT to achieve front-end and back-end authentication?

How does Spring Boot integrate JWT to achieve front-end and back-end authentication?

WBOY
Release: 2023-05-18 13:19:06
forward
1449 people have browsed it

JWT Introduction

JWT (full name: Json Web Token) is an open standard (RFC 7519) that defines a compact, self-contained way to communicate between parties as a JSON object. securely transmit information between

Why use JWT

What are the disadvantages of traditional session authentication?

  • Each user's login information will be saved in the server's Session. As the number of users increases, the server overhead will increase significantly.

  • Session information is stored in the server's memory, which will cause failure for distributed applications. Although the session information can be stored uniformly in the Redis cache, this may increase the complexity. sex.

  • Since Session authentication is based on Cookie, it is not applicable to non-browser terminals and mobile terminals.

  • The front-end and back-end separation system, because the front-end and back-end are cross-domain, and cookie information cannot be crossed, so session authentication cannot continue cross-domain authentication.

Advantages of JWT authentication

  • Simple: JWT Token data volume is small and the transmission speed is also very fast.

  • Cross-language: JWT Token is stored on the client in JSON encrypted form, so JWT is cross-language and supported by any web form. Cross-platform: does not rely on cookies and sessions, and does not need to store session information on the server. It is very suitable for distributed applications and can be used for expansion.

JWT data structure

How does Spring Boot integrate JWT to achieve front-end and back-end authentication?

#Header

The first part of JWT is the header part, which is a description of JWT A Json object of metadata, usually as shown below.

{
    "alg": "HS256",
    "typ": "JWT"
}
Copy after login

The alg attribute indicates the algorithm used for signature, the default is HMAC SHA256 (written as HS256), the typ attribute indicates the type of token, and JWT tokens are uniformly written as JWT.

Payload

The second part of JWT is Payload, which is also a Json object. In addition to containing the data that needs to be passed, there are seven default fields to choose from. iss: Issuer exp: Expiration time sub: Subject aud: User nbf: Not available before iat: Release time jti: JWT ID is used to identify this JWT

{
    //默认字段
    "sub":"主题123",
    //自定义字段
    "name":"java",
    "isAdmin":"true",
    "loginTime":"2021-12-05 12:00:03"
}
Copy after login

It should be noted that by default JWT is unencrypted and anyone can interpret its content, so if you have some sensitive information, do not store it here to prevent information leakage. JSON objects are also converted to strings using the Base64 URL algorithm and saved.

Signature

The signature hash part is to sign the above two parts of data. It needs to use base64 encoded header and payload data, and generate a hash through the specified algorithm to ensure that the data will not be tamper.

Spring Boot integrated JWT

Introducing Jwt package

<dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.1</version>
  </dependency>
Copy after login

Writing jwt tool class

public class JwtUtil
{
//创建jwt
public static String createJWT(String subject, String issue, Object claim,
            long ttlMillis)
    {
       //当前时间
        long nowMillis = System.currentTimeMillis();
        //过期时间
        long expireMillis = nowMillis + ttlMillis;
        String result = Jwts.builder()
                .setSubject(subject) //设置主题
                .setIssuer(issue) //发行者
                .setId(issue)//jwtID
                .setExpiration(new Date(expireMillis)) //设置过期日期
                .claim("user", claim)//主题,可以包含用户信息
                .signWith(getSignatureAlgorithm(), getSignedKey())//加密算法
                .compressWith(CompressionCodecs.DEFLATE).compact();//对载荷进行压缩

        return result;
    }
    
    // 解析jwt
    public static Jws<Claims> pareseJWT(String jwt)
    {
        Jws<Claims> claims;
        try
        {
            claims = Jwts.parser().setSigningKey(getSignedKey())
                    .parseClaimsJws(jwt);
        }
        catch (Exception ex)
        {
            claims = null;
        }
        return claims;
    }

   //获取主题信息
    public static Claims getClaims(String jwt)
    {
        Claims claims;
        try
        {
            claims = Jwts.parser().setSigningKey(getSignedKey())
                    .parseClaimsJws(jwt).getBody();
        }
        catch (Exception ex)
        {
            claims = null;
        }
        return claims;
    }
  }
  
   /**
     * 获取密钥
     * 
     * @return Key
     */
    private static Key getSignedKey()
    {
        byte[] apiKeySecretBytes = DatatypeConverter
                .parseBase64Binary(getAuthKey());
        Key signingKey = new SecretKeySpec(apiKeySecretBytes,
                getSignatureAlgorithm().getJcaName());
        return signingKey;
    }
    
    private static SignatureAlgorithm getSignatureAlgorithm()
    {
        return SignatureAlgorithm.HS256;
    }
  
  //获取密钥,可以动态配置
  public static String getAuthKey()
  {
        String auth = "123@#1234";
  }
Copy after login

Token authentication interceptor

 Component
public class TokenInterceptor extends HandlerInterceptorAdapter
{
    public static Log logger = LogManager.getLogger(TokenInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception
    {
        String uri = request.getRequestURI();
        logger.info("start TokenInterceptor preHandle.." + uri);
         
		//需要过滤特殊请求
        if (SystemUtil.isFree(uri) || SystemUtil.isProtected(uri))
        {
            return true;
        }
        
		
        String metohd=request.getMethod().toString();
        logger.info("TokenInterceptor request method:"+metohd);
        //options 方法需要过滤
        if("OPTIONS".equals(metohd))
        {
            return true;   
        }
        
		//是否开启token认证
        boolean flag = SystemUtil.getVerifyToken();
        ResponseResult result = new ResponseResult();
		//从请求的head信息中获取token
        String token = request.getHeader("X-Token");

        if (flag)
        {
            if(StringUtils.isEmpty(token))
            {
                token=request.getParameter("X-Token");    
            }
            // token不存在
            if (StringUtils.isEmpty(token))
            {
                result.setCode(ResultCode.NEED_AUTH.getCode());
                result.setMsg(ResultCode.NEED_AUTH.getMsg());
                WebUtil.writeJson(result, response);
                return false;
            }
            else
            {
                Claims claims = JwtUtil.getClaims(token);
                String subject = "";
                if (claims != null)
                {
                    subject = claims.getSubject();
                    // 验证主题
                    if (StringUtils.isEmpty(subject))
                    {
                        result.setCode(ResultCode.INVALID_TOKEN.getCode());
                        result.setMsg(ResultCode.INVALID_TOKEN.getMsg());
                        WebUtil.writeJson(result, response);
                        return false;
                    }								
                }
                else
                {
                    result.setCode(ResultCode.INVALID_TOKEN.getCode());
                    result.setMsg(ResultCode.INVALID_TOKEN.getMsg());
                    WebUtil.writeJson(result, response);
                    return false;
                }
            }
        }
        return true;
    }

}
Copy after login

Configuration interception Device

@Configuration
public class WebConfig implements WebMvcConfigurer
{
    @Resource
    private TokenInterceptor tokenInterceptor;

    public void addInterceptors(InterceptorRegistry registry)
    {
        registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
    }
 }
Copy after login

Login verification process

How does Spring Boot integrate JWT to achieve front-end and back-end authentication?

Sample code

@RequestMapping("login")
public Result login(HttpServletResponse response)
{
    Map<String, Object> map = new HashMap<>();
    //
    Result result = loginAuth(user);
    int code = result.getCode();
            //登录认证成功
    if (code ==ResultCode.SUCCESS)
    {
        //默认为7天
        Long ttlMillis = 7*1000 * 60 * 60 * 24;
        //过期时间
        long expreTime = System.currentTimeMillis() + ttlMillis;
        String tokenKey = UUID.randomUUID().toString();
        String tokenId = JwtUtil.createJWT(user.getUserId(), tokenKey,
                user.getPassword(), expreTime);                   
        map.put("expreTime", expreTime);				
        map.put("tokenId", tokenId);           
    }
    else
    {
        logger.error("login error:" +FastJsonUtil.toJSONString(result));
    }
    return result;
}
Copy after login

The above is the detailed content of How does Spring Boot integrate JWT to achieve front-end and back-end authentication?. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:yisu.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template