Use custom annotation + AOP, JWT achieve access token authentication and authorization

JWT: Json Web Token is a solution to achieve token, which has three parts, header (head), payload (carrier), signature (the signature).

The first part is jwt header, header comprises two main portions, means ALG encryption type, optional value HS256, RSA, type JWT is a fixed value, indicates the type of token.

The second part payload carrier, details payload is the token, generally comprises iss issuer, exp expiration time, user information Sub, AUD receiver, and other information, and can be custom parameter set values.

The third part is a signature signature, Base64 (header) .Base64 (payload) to get a bit Base64 encoded string, we call it bit encodingstring. Then use the HS256 (encodingstring, keys), calculated signature.

These three parts together, is a complete JWT TOKEN, a secret key stored in the server's private key.

The head support, signature . Connected to afford a the JWT.

For example: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxIn0.dQMt-whQl9DmFOo-JIupTPRKZkApwBhUjSvIRuZ9lF8

Differences Session id and stored in the
Session stored user id's biggest drawback is that to take up a large amount of server memory, for larger applications may have saved many of the state. In general, large applications also need the help of some KV database and a series of mechanisms to achieve Session cache memory.

The JWT way the user dispersed to the client, the server can significantly reduce the memory pressure. In addition to user id, you can also store other information associated with the user, such as user roles, user gender.

Here we have integrated a demo, custom annotations + aop to implement the login authentication token.

pom.xml dependence

<!-- 使用jwt验证 -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency> 

Custom annotation

package com.example.auth.annotation;

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

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface PassToken {

    boolean required() default true;
}
 

package com.example.auth.annotation;

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

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {

    boolean required() default true;
}

An entity

package com.example.auth.annotation;

public class User {

    private String id;
    private String username;
    private String password;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    
}


JWT generator

package com.example.auth.annotation;

import org.springframework.stereotype.Component;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
@Component
public class JWTUtil {

    String getToken to public (the User User) {
        / **
         * Set effective two minutes, add parameters withClaim, set an expiration time withExpiresAt.
         * using a personal password as the key
         * /
        a Date = new new DATE a Date (System.currentTimeMillis () + 1000 60 * 2 *);
        String token = JWT.create ()
                . .withAudience (user.getId ()) withClaim (. "City", "XM") withExpiresAt (DATE)
                .sign (Algorithm.HMAC256 (user.getPassword ()) );
        return token;
    }
}

Decryption


service and serviceImpl, here I did not go to check the value of the database, all of you to deal with

package com.example.auth.service;

import com.example.auth.annotation.User;

public interface UserSerivce {

    User findUserById(String userId);

    User findByUsername(User user);
}
 

package com.example.auth.service.impl;

import org.springframework.stereotype.Service;

import com.example.auth.annotation.User;
import com.example.auth.service.UserSerivce;

@Service
public class UserServiceImpl implements UserSerivce{

    @Override
    public User findUserById(String userId) {
        User user = new User();
        user.setId("1");
        user.setUsername("admin");
        user.setPassword("admin");
        return user;
    }

    @Override
    public User findByUsername(User user) {
        User u = new User();
        u.setId("1");
        u.setUsername("admin");
        u.setPassword("admin");
        return u;
    }

}
 

AOP interceptors

package com.example.auth.annotation;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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 com.example.auth.service.UserSerivce;

{class AuthenticationInterceptor HandlerInterceptor from the implements public
    @Autowired
    UserSerivce that userService;
    @Override
    public Boolean The preHandle (the HttpServletRequest HttpServletRequest, HttpServletResponse the HttpServletResponse, Object Object) throws Exception {
        String = httpServletRequest.getHeader token ( "token"); // remove the token from the http request header
        // If not map directly to a method of
        IF (! (HandlerMethod the instanceof Object)) {
            return to true;
        }
        HandlerMethod HandlerMethod = (HandlerMethod) Object;
        method, method handlerMethod.getMethod = ();
        // check passtoken comment, there is skip authentication
        if (method.isAnnotationPresent (PassToken.class)) {
            PassToken = method.getAnnotation PassToken (PassToken.class);
            IF (passToken.required ()) {
                return to true;
            }
        }
        // check annotated no user privileges
        IF (method.isAnnotationPresent (UserLoginToken.class)) {
            UserLoginToken userLoginToken method.getAnnotation = (UserLoginToken.class);
            IF (userLoginToken.required ()) {
                // perform authentication
                IF (token == null) {
                    the throw new new RuntimeException ( "no token, please re-login");
                }
                // get token ID in the User
                String the userId;
                the try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("401");
                }
                User user = userService.findUserById(userId);
                if (user == null) {
                    throw new RuntimeException("用户不存在,请重新登录");
                }
                // 验证 token
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new RuntimeException("401");
                }
                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 {
    }
    
}


Configuration class 

package com.example.auth.annotation;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(authenticationInterceptor())
                .addPathPatterns("/**");   
    }
    @Bean
    public AuthenticationInterceptor authenticationInterceptor() {
        return new AuthenticationInterceptor();
    }
}

Test Controller

package com.example.auth;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.example.auth.annotation.JWTUtil;
import com.example.auth.annotation.User;
import com.example.auth.annotation.UserLoginToken;
import com.example.auth.service.UserSerivce;

@RestController
@RequestMapping("api")
public class UserApi {
    @Autowired
    UserSerivce userService;
    @Autowired
    JWTUtil tokenService;
    //登录
    @PostMapping("/login")
    public Object login(@RequestBody User user){
        
        JSONObject jsonObject=new JSONObject();
        User userForBase=userService.findByUsername(user);
        if(userForBase==null){
            
            jsonObject.put("message","登录失败,用户不存在");
            return jsonObject;
        }else {
            
            if (!userForBase.getPassword().equals(user.getPassword())){
                
                jsonObject.put("message","登录失败,密码错误");
                return jsonObject;
            }else {
                
                String token = tokenService.getToken(userForBase);
                jsonObject.put("token", token);
                jsonObject.put("user", userForBase);
                return jsonObject;
            }
        }
    }
    
    @UserLoginToken
    @GetMapping("/getMessage")
    public String getMessage(){
        return "你已通过验证";
    }
}
 

Test shots.

 

 

 

 

 

Guess you like

Origin blog.csdn.net/u012373281/article/details/91361300