SpringBoot使用拦截器实现token身份验证

SpringBoot使用拦截器实现token身份验证

浏览器的传统session会话 无法应用于安卓浏览器 因此需要token身份验证 我这里使用拦截器配合Redis实现此功能

AuthorizationInterceptor类:

package com.ls.reg.config;

import com.ls.reg.bin.base.Result;
import com.ls.reg.utils.JSONUtilsEx;
import com.ls.reg.utils.RedisUtilsEx;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

@Component
public class AuthorizationInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");//开发环境允许跨域
        //如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }


        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();

        Enumeration enu = request.getParameterNames();
        List<String> list = new ArrayList();
        String user_token = "";
        while (enu.hasMoreElements()) {
            String paraName = (String) enu.nextElement();
            if(paraName.equals("user_token")) {
                user_token =  request.getParameter(paraName);
                list.add(request.getParameter(paraName));
            } else {
                list.add(request.getParameter(paraName));
            }
        }

        if (method.getAnnotation(MustLogin.class) != null) {
            // 如果 加这个注解了 说明用户 必须要登录 必须传 user_token
            if(StringUtils.isBlank(user_token)) {
                Result result = new Result(Result.NOLOGIN,"请登录", "");
                String serialize = JSONUtilsEx.serialize(result);
                returnErrorMessage(response,serialize);
                return false;
            }else {
                String string = RedisUtilsEx.get("session-"+user_token);
                if(StringUtils.isBlank(string)) {
                    // 缓存里面不存在 就说明 用户信息 失效
                    //response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    Result result = new Result(Result.NOLOGIN,"请登录", "");
                    String serialize = JSONUtilsEx.serialize(result);
                    returnErrorMessage(response,serialize);
                    return false;
                }else {
                    // 重新登录 要刷新下 用户 user-token          //(10小时不操作自动掉线)
                    RedisUtilsEx.set("session-"+user_token, string,60*60*10);
                }
            }
        }

        return true;
    }

    private void returnErrorMessage(HttpServletResponse response, String errorMessage) throws IOException {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        out.print(errorMessage);
        out.flush();
    }

}

注意 需要将以上拦截器在WebMvcConfigurer中注册:

package com.ls.reg.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MySpringBootConfig implements WebMvcConfigurer {
    @Autowired
    private AuthorizationInterceptor interceptor;

    /**
     * 加载拦截器
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        super.addInterceptors(registry);
        InterceptorRegistration loginRegistry =  registry.addInterceptor(interceptor);
        loginRegistry.excludePathPatterns("/init/**");
    }

    /**
     * 配置static的静态资源访问
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");

    }


}

注解 MustLogin

package com.ls.reg.config;

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

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MustLogin {
	
}

在登录接口中向缓存中加入user_token并将其返回给前端,前端使用本地储存或者其他的存储方式将其存储,在访问其他需要身份验证的接口时将其作为入参传入即可

String userToken = StaticUtils.getUserToken();//此处的token是UUID

String oldToken = RedisUtilsEx.get("session-user");
if(StringUtils.isNotBlank(oldToken)) {
 //要删除以前的token
     //RedisUtilsEx.del("session-"+oldToken);
}
RedisUtilsEx.set("session-"+userToken, userId, 60*60*10);
RedisUtilsEx.set("session-user-"+userId, userToken, 60*60*10);
return userToken;

那么接下来 只需要在必须登录才可访问的接口中加上此注解 即可实现身份登录验证

    @PostMapping(value="/checkLogin")
    @MustLogin
    public Result checkLogin(
            String user_token
    ) {
        try {
            Integer userId = Integer.parseInt(RedisUtilsEx.get("session-"+user_token));
            return new Result(Result.OK,"验证成功",userId);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(Result.ERROR, e.getMessage(), "");
        }
    }

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注