Now that the front end is separated, the design is based on session to span the problem, and the session synchronization problem before multiple servers, may be lost, so I prefer to use JWT as token authentication JSON Web token

  1. Import the Java-JWT toolkit
 <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.15.0</version>
        </dependency>
Copy the code
  1. Generate a token through JWT

Write a generic TokenService

package cn.soboys.core.authentication;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import org.springframework.stereotype.Service;

import java.util.Date;

/ * * *@author kenx
 * @version 1.0
 * @date2021/6/22 10:23 * Token operation */
@Service("TokenService")
public class TokenService {

    // Expiration time unit milliseconds 7 x 24 x 60 x 60 x 1000
    private final Long tokenExpirationTime = 604800000l;

    / * * *@paramUuid The unique identifier (*) of a user@paramSecret User password *@returnToken generated * /
    public String generateToken(String uuid, String secret) {
        // Recalculate the time before each login
        Date expiresDate = new Date(System.currentTimeMillis() + tokenExpirationTime);
        String token = "";
        token = JWT.create()
                // Set the expiration time
                .withExpiresAt(expiresDate)
                // Set the recipient information, generally the login user
                .withAudience(uuid)// Save the user ID to the token
                // Use the HMAC algorithm
                .sign(Algorithm.HMAC256(secret));// Use password as the token key
        returntoken; }}Copy the code
  1. Write annotations to filter and intercept those that require login authenticationcontroller

PassToken is used to skip login authentication. UserLoginToken indicates that login authentication is required

package cn.soboys.core.authentication;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/ * * *@author kenx
 * @version 1.0
 * @date2021/6/21 17:21 * Skip login authentication */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {
    boolean required(a) default true;
}

Copy the code
package cn.soboys.core.authentication;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/ * * *@author kenx
 * @version 1.0
 * @date2021/6/21 17:22 * Requires login verification */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
    boolean required(a) default true;
}

Copy the code
  1. Writing business exceptionsAuthenticationException

An authentication failure throws an AuthenticationException

package cn.soboys.core.authentication;

import lombok.Data;

/ * * *@author kenx
 * @version 1.0
 * @date2021/6/22 13:58 * Authentication exception */
@Data
public class AuthenticationException extends RuntimeException {

    public AuthenticationException(String message) {
        super(message); }}Copy the code
  1. Write authentication interceptorsAuthenticationInterceptorTo intercept authentication requests
package cn.soboys.core.authentication;

import cn.hutool.extra.spring.SpringUtil;
import cn.soboys.core.ret.ResultCode;
import cn.soboys.mallapi.entity.User;
import cn.soboys.mallapi.service.IUserService;
import cn.soboys.mallapi.service.impl.UserServiceImpl;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/ * * *@author kenx
 * @version 1.0
 * @date2021/6/21 17:24 * User authentication login blocked */

public class AuthenticationInterceptor implements HandlerInterceptor {
    // Get the token from the header
    public static final String AUTHORIZATION_TOKEN = "authorizationToken";


    private  IUserService userService= SpringUtil.getBean(UserServiceImpl.class);

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        String token = httpServletRequest.getHeader(AUTHORIZATION_TOKEN);// Fetch the token from the HTTP request header
        httpServletRequest.setAttribute("token", token);
        // If it is not mapped to the Controller Mapping method directly pass
        if(! (objectinstanceof HandlerMethod)) {
            return true;
        }
        HandlerMethod handlerMethod = (HandlerMethod) object;

        Method method = handlerMethod.getMethod();
        // Check if there are passtoken comments. If there are passtoken comments, the authentication will be skipped
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true; }}// Check whether there are any comments that require user permissions
        //Annotation classLoginAnnotation = handlerMethod.getBeanType().getAnnotation(UserLoginToken.class); // The class level requires a login token
        if (method.isAnnotationPresent(UserLoginToken.class) || handlerMethod.getBeanType().isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken =
                    method.getAnnotation(UserLoginToken.class) == null ?
                            handlerMethod.getBeanType().getAnnotation(UserLoginToken.class) : method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // Perform authentication
                if (token == null) {
                    throw new AuthenticationException("No token, please log in again.");
                }
                // Obtain the user ID in the token
                String userId;
                try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new AuthenticationException("Illegal User");
                }
                User user = userService.getUserInfoById(userId);
                if (user == null) {
                    throw new AuthenticationException("User expired, please log in again.");
                }
                / / authentication token
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getUserMobile())).build();
                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new AuthenticationException("Illegal User");
                }
                return true; }}return true; }}Copy the code