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) {
     // ...
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章