Using JWT to implement token authentication in Java

Keywords: github

1. Implement the annotation classes that skip authentication (PassToken) and require authentication (UserLoginToken)

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

2. Implement getting Token class (TokenService)

@Service
public class TokenService {
    public String getToken(User user) {
        // Expiration time, 5 minutes
        long EXPIRE_TIME = 5*60*1000;
        // Build expiration
        Date expireDate = new Date(System.currentTimeMillis()+EXPIRE_TIME);
        String token = JWT.create().withAudience(user.getId())// Save user id to token
                .withExpiresAt(expireDate)// Set expiration time
                .sign(Algorithm.HMAC256(user.getPassword()));// password as the key of token
        return token;
    }
}

3. Implement the token authentication class (AuthenticationInterceptor)

public class AuthenticationInterceptor implements HandlerInterceptor {
    @Autowired
    UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
        String token = httpServletRequest.getHeader("token");// Take token from http request header
        // 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 whether there is a passtoken comment, and skip authentication if there is one
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }
        //Check for comments that require user rights
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // Executive certification
                if (token == null) {
                    throw new RuntimeException("Not signed in, please sign in");
                }
                // Get user id in token
                String userId;
                try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("token Wrong authentication name, please login again");
                }
                User user = userService.findUserById(userId);
                if (user == null) {
                    throw new RuntimeException("User does not exist, please login again");
                }
                // Verify token
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new RuntimeException("token The authentication password is wrong or the login has expired. Please login again");
                }
                return true;
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest,
                           HttpServletResponse httpServletResponse,
                           Object o, ModelAndView modelAndView) throws Exception {

    }
    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest,
                                HttpServletResponse httpServletResponse,
                                Object o, Exception e) throws Exception {
    }
}

4. Because you need to throw an exception, implement a global exception capture class ()

@ControllerAdvice
public class GloablExceptionHandler {
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Object handleException(Exception e) {
        String msg = e.getMessage();
        if (msg == null || msg.equals("")) {
            msg = "Server error";
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("status", 500);
        jsonObject.put("message", msg);
        return jsonObject;
    }
}

5. Add the InterceptorConfig to verify all the mapping paths

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**");    // Block all requests, and determine whether to log in by judging whether there is @ UserLoginToken annotation
    }

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

6. Implement access class (UserController)

@RestController
@RequestMapping("/api")
public class UserController {
    @Autowired
    UserService userService;
    @Autowired
    TokenService tokenService;
    //Sign in
    @PostMapping("/login")
    public Object login(@RequestBody User user){
        JSONObject jsonObject=new JSONObject();
        User userForBase=userService.findUserById("user");
        if(userForBase==null){
            jsonObject.put("message","Login failed,user does not exist");
            return jsonObject;
        }else {
            if (!userForBase.getPassword().equals(user.getPassword())){
                jsonObject.put("message","Login failed,Password error");
                return jsonObject;
            }else {
                String token = tokenService.getToken(userForBase);
                jsonObject.put("token", token);
                jsonObject.put("user", userForBase);
                return jsonObject;
            }
        }
    }

    @UserLoginToken
    @GetMapping("/getMessage")
    public Object getMessage(){
        Map<String, Object> retMap = new HashMap<>();
        retMap.put("message", "You have passed the verification");
        retMap.put("status", 200);
        return retMap;
    }
}

7. Post man access

* http://127.0.0.1:8080/api/login

* http://127.0.0.1:8080/api/getMessage

No access effect before login

Login successfully

Login succeeded with token access

Access after token error or login time expires

Source code address of github project

https://github.com/kenyonlover/spring_boot_jwt_test
Published 11 original articles, praised 0, visited 1645
Private letter follow

Posted by fean0r on Mon, 03 Feb 2020 06:53:22 -0800