springBoot之单点登入 spring session + redis : 实现session共享

说明

分布式环境下的session共享&自定义注解&拦截器,实现接口的动态登入拦截

1.相关maven依赖     

<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- spring session + redis -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

2)配置yml


            spring
                session:
                    store-type: redis #session交由redis保存
               redis:
                        host: localhost

                        账号&密码 
                        port: 6379
                        timeout: 3000
                        usePool: true
                        pool:
                          max-idle: 50
                          maxTotal: 100
                        database: 2

3)配置类

 

一.项目启动类:

@EnableRedisHttpSession(maxInactiveIntervalInSeconds = session的存活时间/秒)

@Bean//添加
public static ConfigureRedisAction configureRedisAction() {
   return ConfigureRedisAction.NO_OP;
}

二.注册拦截器

@Configuration
public class WebConfigurer implements WebMvcConfigurer {
/**
    * 注册拦截器
    *
    *
    * @param registry
    */
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      //registry.addInterceptor(loggedInInterceptor).addPathPatterns("/**").excludePathPatterns("/login.ctrl");//添加请求路径拦截,以及不包含的路径(不拦截)
      //在注册时不指定拦截路径,通过拦截器中判断是否函数带有isLogin(自定义)的注解来拦截
      registry.addInterceptor(loggedInInterceptor);
   }
}

4)自定义注解与拦截器

/**
 * 自定义注解:接口拦截注解,配置在需要登入后访问的controller层函数上
 *
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface isLogin{
}

/**
 * 拦截器
 */
@Component
public class LoggedInInterceptor implements HandlerInterceptor {

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    /**
     * 校验session缓存用户信息
     * 
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        IsLoggedin isLoggedin = handlerMethod.getMethodAnnotation(IsLoggedin.class);
        if (isLoggedin == null) {// 函数上是否携带@isLogin 自定义注解,没有则不拦截
            return true;
        }
        Boolean result_status = false;
        User user;
        if (request.getSession().getAttribute("userInfo") != null) {
            user = (User) request.getSession().getAttribute("userInfo");
            if (user != null) {
                result_status = true;
            }
        }
        if (!result_status) {
            if (request.getHeader("x-requested-with") != null && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
                response.setStatus(444);
                response.setContentType("application/json");
                response.setCharacterEncoding("UTF-8");
                response.getWriter().print("{\"error\":\"未登录,请先登录。\"}");
                response.flushBuffer();
            }
            else { 
                response.setContentType("application/json");
                response.setCharacterEncoding("UTF-8");
                response.getWriter().print("{\"errorCode\":444}");
                response.flushBuffer();
            }
        }
        return result_status;
    }
}

测试

1.登入接口成功后,将用户信息放入session;

request.getSession().setAttribute("userInfo", userInfo);

2.在接口声明时配置注解isLogin

@isLogin
@RequestMapping(value = "/test.ctrl", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
public Map<String, Object> test(@RequestBody Map<String, Object> params) {
     // ...
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章