Spring boot uses Jwt to deal with cross domain authentication

Why do we need user authentication in front and back end development? The reason is that the HTTP protocol does not store the status, which means that when we verify a user through the account password, the user will forget the data just before the next request. So our program doesn't know who it is. Therefore, in order to ensure the security of the system, it is necessary to verify whether the user is in the login state.

1, Composition of JWT

JWT consists of Header, Payload and Signature, separated by.

The following is a real jwt, which is a string, but it stores very important information.

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyYXljaGVuIiwiaWQiOjIsIm5hbWUiOiJyYXkiLCJwYXNzd29yZCI6IjMyMSIsImlhdCI6MTU5MDI5OTU0OCwiZXhwIjoxNTkwMzg1OTQ4fQ.ORJNldDIfffg7D3_xu0_dBWb16y4fPLtw_r6qgScFpQ

Header:

The first part is that the request header consists of two parts, alg and typ. The first part specifies the algorithm and the second part specifies the type.

Payload

The second part is the main body information, which is used to store JWT basic information, or our information.

Signature

The third part is mainly used to sign the first part and the second part to verify whether the Token is initiated by our server, and secret is our key.

2, Using jwt for verification in spring boot project

Specific process:

  • Send the user name and password to the back end
  • The backend performs the verification. If the verification succeeds, a token will be generated and sent to the client
  • The client saves the token itself, and the next request is to visit the server with the token in the request header of Http protocol, and compare and verify the token information saved in the server.

1. First introduce the jar package

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

2. Use tool class to generate token and verify token (user's information is stored in the method of generating token)

public class JwtUtils {

    //publisher
    public static final String SUBJECT="raychen";
    //Expiration time one day
    public static final long EXPIRE=1000*60*60*24;
    //secret key
    public static final String APPSECRET="raychen11";

    /**
     * Generate jwt
     * @param user
     * @return
     */
    public static String geneJsonWebToken(User user){
        if(user==null || user.getId()==null || user.getName()==null || user.getPassword()==null){
            return null;
        }
        String token=Jwts.builder().setSubject(SUBJECT)
                .claim("id",user.getId())
                .claim("name",user.getName())
                .claim("password",user.getPassword())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis()+EXPIRE))
                .signWith(SignatureAlgorithm.HS256,APPSECRET).compact();

        return token;
    }

    /**
     * Verification token
     * @param token
     * @return
     */
    public static Claims checkJWT(String token){
        //Imitative token Or it will report an error if it has expired
        try {
            final Claims claims=Jwts.parser().setSigningKey(APPSECRET).parseClaimsJws(token).getBody();
            return claims;
        }catch (Exception e){
            System.out.println("catch...");
        }
        return null;
    }
}

3. User defined annotation (token verification)

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckToken {
    boolean required() default true;
}

4. Write config to remove all requests from the background to the interceptor first (the interceptor returns true before the user can request to the interface)

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**");    // Block all requests by judging whether there are @LoginRequired Comments determine whether login is required
    }

    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
}

5. Define interceptor (for the request requiring token verification, verify that the success of verification returns true and the failure returns false, and the interface cannot be requested)

public class AuthenticationInterceptor implements HandlerInterceptor {

    public static final Gson gson=new Gson();
    /**
     * Intercept before entering the controller
     * @param request
     * @param response
     * @param object
     * @return
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
        // If it is not mapped to a method directly through
        if (!(object instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //Check if there is LoginToken Note, skip authentication if any
        if (method.isAnnotationPresent(LoginToken.class)) {
            LoginToken loginToken = method.getAnnotation(LoginToken.class);
            if (loginToken.required()) {
                return true;
            }
        }

        //No need ahead token Verified from http Remove from request header token
        String token = request.getHeader("token");
        //Check for comments that require user rights
        if (method.isAnnotationPresent(CheckToken.class)) {
            CheckToken checkToken = method.getAnnotation(CheckToken.class);
            if (checkToken.required()) {
                if(token!=null){
                    Claims claims= JwtUtils.checkJWT(token);
                    if(null==claims){
                        sendJsonMessage(response, JsonData.buildError("token Wrong"));
                        return false;
                    }
                    Integer userId= (Integer) claims.get("id");
                    String name = (String) claims.get("name");

                    request.setAttribute("userId",userId);
                    request.setAttribute("name",name);
                    return true;
                }
                //token by null Back to a paragraph json To the front end
                sendJsonMessage(response, JsonData.buildError("Please log in"));
                return false;
            }
        }
        //Return directly without annotation true
        return true;
    }

        /**
         * Response data to front end
         * @param response
         * @param obj
         * @throws IOException
         */
        public static void sendJsonMessage (HttpServletResponse response, Object obj) throws IOException {
            response.setContentType("application/json; charset=utf-8");
            PrintWriter writer = response.getWriter();
            writer.print(gson.toJson(obj));
            writer.close();
            response.flushBuffer();
        }
}

After the user logs in successfully, the token is generated using the tool class. The token is not stored in the server, but directly returned to the client. The next time the client requests the server, the tool class is used to verify whether the token in the header is legal.

Tags: JSON Spring

Posted on Mon, 25 May 2020 01:38:27 -0400 by sharyn