週二. 8 月 11th, 2020

IT Skills 波林

Polin WEI – 資訊工作者的技術手札

spring boot 對於 axios 執行 ajax 遇到 response.status:302 的處理方式

2 min read
StatusCode-302

spring boot 對於 axios 執行 ajax 遇到 response.status:302 的處理方式

 

jquery 與 axios 對於 spring boot 的 ajax 請求處理 裡談到現行的網頁操作使用 ajax 技術來節省頻寛,若想與 Vue.js 結合,則不妨使用Axios。而在使用  ajax 技術常會遇到一件事是  session timeout,後端主機會反饋一個 Status Code: 302,且 post url 轉指向 login。這時操作畫面沒有變化,但已經無法與後端主機取得資料。

StatusCode-302

 

要解決這個問題需要前端 HTML 的 java script 與後端主機 spring boot 的 Interceptor 作著手。

首先,前端 ( Front-End ) HTML 裡的 java script 對 axios 送出前加入 "X-REQUEST-TYPE":"axios",以及收到後端主機 spring boot 的 Interceptor 的 401 錯誤作導向登入畫面。

// http request 欄截
axios.interceptors.request.use(
  config => {    
 config.headers = { // 如果沒有cors的問題則可以都不加
   "X-REQUEST-TYPE":"axios"
 };
 return config;
  },
  error => {
 console.log(error);
 return Promise.reject(error);
  }
);
// 異常處理
axios.interceptors.response.use(
  response => {
   console.log(response.headers["axios-session-status"]);
   if (response.headers["axios-session-status"]=="Unauthorized"){                     
    console.log("未經授權");
   }
 return response;
  },
  err => {
 if (err && err.response) {
  this.isResponseOk = false;
  this.isResponseError = true;
   switch (err.response.status) {
  case 401:                   
    console.log("此作業timeout");
    window.location.href = "/login";
    break;
  case 403:
    console.log("此作業沒有權限");
    break;
  case 404:
    console.log("找不到該頁面");
    break;
  case 500:
    console.log("伺服器出錯");
    break;
  case 503:
    console.log("服務失效");
    break;
  default:
    console.log("後台存取作業有錯誤");
   }
 } else {                   
   console.log("連接到服務器失敗");                   
 }
 return Promise.resolve(err.response);
  }
);

 

設置好前端  ( Front-End ) HTML 裡的 java script,再來對 spring boot 作設置。

1.) 在 WebMvcConfigurer 註冊 Interceptor: SecurityInterceptor.class

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    /**
     * 註冊 Interceptor 
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 對帳號登入後的偵測, URL 需要以 /auth 為開頭才會有作用
         SecurityInterceptor securityInterceptor = new SecurityInterceptor();
         registry.addInterceptor(securityInterceptor).addPathPatterns("/auth/**").addPathPatterns("/login");
    }
}

 

2.) 建立 SecurityInterceptor.class

在 preHandle 攔截 x-request-type ,判斷是否為前端設置的 axios ,並判斷 auth.getPrincipal().equals("anonymousUser")  ,若是的話,那就是 session timeout 了,所以設置 Header 為 Unauthorized: response.setHeader("Axios-Session-Status", "Unauthorized");

再到 postHandle 攔截 Header 為 Unauthorized 的部份,在返回前端  ( Front-End ) 前,將 Header 的 status 設為 401:response.setStatus(401); ,這樣就完成了。

public class SecurityInterceptor extends HandlerInterceptorAdapter {

 private final Logger logger = LoggerFactory.getLogger(this.getClass());
        private Authentication auth;
 
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
   throws Exception {

  logger.debug("SecurityInterceptor - preHandle");

  auth = SecurityContextHolder.getContext().getAuthentication();
    Map<String, String> requestHearderNames = getHeadersInfo(request);
    // 取 axios 的 config.headers 裡的 "x-request-type" 參數值 
    String requestType = Objects.isNull(requestHearderNames.get("x-request-type")) ? "submit" : requestHearderNames.get("x-request-type");
    if ( requestType.equals("axios") ) {
        if( auth.getPrincipal().equals("anonymousUser") ){              
            response.setHeader("Axios-Session-Status", "Unauthorized"); // 響應頭設定session狀態: 沒有認證的 axios-ajax 請求
        } else {
            response.setHeader("Axios-Session-Status", "authorized");
        }
    } else {
        response.setHeader("Axios-Session-Status", "Not-Axios"); // 響應頭設定session狀態
    }

  return super.preHandle(request, response, handler);
 }

 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
   ModelAndView modelAndView) throws Exception {
 
  logger.debug("SecurityInterceptor - postHandle");
  String axiosStatus = response.getHeader("Axios-Session-Status");
  if (axiosStatus.equals("Unauthorized")) {         
   response.setStatus(401);
  }
  
 }
 
 private Map<String, String> getHeadersInfo(HttpServletRequest request) {
  Map<String, String> map = new HashMap<String, String>();
  Enumeration headerNames = request.getHeaderNames();
  while (headerNames.hasMoreElements()) {
   String key = (String) headerNames.nextElement();
   String value = request.getHeader(key);
   map.put(key, value);
  }
  return map;
 }

}

 

Copyright © All rights reserved. | Newsphere by AF themes.