Interface permission control (springboot)

Posted by Develop_Sake on Wed, 26 Jan 2022 03:15:03 +0100

Principle: first, call login, and a token will be passed to the front end. Later interfaces need to use this token. The front end needs to put the token into the request header and pass it when calling the interface. After the back end obtains the token, compare the obtained token with that in the database. If it is the same, it means that it has been logged in and the interface can be called.

Implementation resolution:

1. First, you need to log in, generate a token, and store the token in the database. How do you store the token?

Considering that this token basically does not change and is frequently used, it is a good choice to store it in redis. Later, the tokens in the request header are compared with those in redis. If you want to find this token in redis, you need different key s to identify different tokens. For example, token1:"12345",token2:"23456", so you need to define an easy to find identifier, I use cache_ The specific token value is in this format.

2. The second question is, do you write a method to obtain the token before each interface?

This method is definitely undesirable. If there are more interfaces, it will be very troublesome. Therefore, I use spring's AOP aspect oriented programming, which is to build a aspect before each interface in the controller, and uniformly execute a method to judge the token in this aspect. In this way, it can be managed uniformly without writing code repeatedly, Here, we should not forget to filter the login interface, which does not need a token.

3. If the user has not operated for a long time, the token needs to be automatically destroyed for security reasons. How to do it? Scheduled tasks?

Similar to scheduled tasks, redis can set a survival time for the data in it, which will be automatically deleted when the time comes. However, for the sake of the user's experience, it is necessary to refresh the survival time every time the interface is adjusted, so as to optimize the user's experience.

The main implementation codes are as follows:

//Establish tangent point
@Pointcut("execution(* com.example.blog.controller.*.*(..))")
    public void controllerMethod(){}

    @Before("controllerMethod()")
    public void LogRequestInfo(JoinPoint joinPoint){
        RequestAttributes requestAttribute = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)requestAttribute).getRequest();
        // Print request content
        log.info("----------------------------------------------------------Interface call initiation----------------------------------------------------------");
        log.info("Request received, request mode={},Request address={},request IP={},Request method name={},Request parameters={}",request.getMethod(),request.getRequestURL().toString(),
                ToolsUtil.getServerIp(),joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
        //Filter login interface
        if(!joinPoint.getSignature().getName().equals("userLogin")){
            //Permission verification before interface
            String key = "cache_token_"+ RequestUtil.getUserId();
            if(ParamUtil.empty(redisUtil.get(key))){
                log.info("Interface call failed:Return results=" + ResponseCode.NoAuthor.toString());
                log.info("----------------------------------------------------------End of interface call----------------------------------------------------------");
                throw new CommonException(ResponseCode.NoAuthor.getMessage(),ResponseCode.NoAuthor.getMessage_en(),ResponseCode.NoAuthor.getErrorCode());
            }
            if(!Objects.equals(RequestUtil.getToken(), redisUtil.get(key))){
                log.info("Interface call failed:Return results=" + ResponseCode.NOPOWER.toString());
                log.info("----------------------------------------------------------End of interface call----------------------------------------------------------");
                throw new CommonException(ResponseCode.NOPOWER.getMessage(),ResponseCode.NOPOWER.getMessage_en(),ResponseCode.NOPOWER.getErrorCode());
            }
            //Refresh token lifetime
            redisUtil.expire(key,4*60*60);
        }
    }

Topics: Java Redis Spring Boot AOP