日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

今天要和小伙伴們聊一聊 Spring Security 中的另外一個問題,那就是在 Spring Security 中未獲認證的請求默認會重定向到登錄頁,但是在前后端分離的登錄中,這個默認行為則顯得非常不合適,今天我們主要來看看如何實現未獲認證的請求直接返回 JSON ,而不是重定向到登錄頁面。

大家知道,在自定義 Spring Security 配置的時候,有這樣幾個屬性:

@Override
protected void configure(HttpSecurity http) throws Exception {
 http.authorizeRequests()
 .anyRequest().authenticated()
 .formLogin()
 .loginProcessingUrl("/doLogin")
 .loginPage("/login")
 //其他配置
 .permitAll()
 .and()
 .csrf().disable();
}

這里有兩個比較重要的屬性:

  • loginProcessingUrl:這個表示配置處理登錄請求的接口地址,例如你是表單登錄,那么 form 表單中 action 的值就是這里填的值。
  • loginPage:這個表示登錄頁的地址,例如當你訪問一個需要登錄后才能訪問的資源時,系統就會自動給你通過重定向跳轉到這個頁面上來。

這種配置在前后端不分的登錄中是沒有問題的,在前后端分離的登錄中,這種配置就有問題了。我舉個簡單的例子,例如我想訪問 /hello 接口,但是這個接口需要登錄之后才能訪問,我現在沒有登錄就直接去訪問這個接口了,那么系統會給我返回 302,讓我去登錄頁面,在前后端分離中,我的后端一般是沒有登錄頁面的,就是一個提示 JSON,例如下面這樣:

@GetMApping("/login")
public RespBean login() {
 return RespBean.error("尚未登錄,請登錄!");
}

也就是說,當我沒有登錄直接去訪問 /hello 這個接口的時候,我會看到上面這段 JSON 字符串。在前后端分離開發中,這個看起來沒問題(后端不再做頁面跳轉,無論發生什么都是返回 JSON)。但是問題就出在這里,系統默認的跳轉是一個重定向,就是說當你訪問 /hello 的時候,服務端會給瀏覽器返回 302,同時響應頭中有一個 Location 字段,它的值為 http://localhost:8081/login ,也就是告訴瀏覽器你去訪問 http://localhost:8081/login 地址吧。瀏覽器收到指令之后,就會直接去訪問 http://localhost:8081/login 地址,如果此時是開發環境并且請求還是 Ajax 請求,就會發生跨域。因為前后端分離開發中,前端我們一般在 NodeJS 上啟動,然后前端的所有請求通過 NodeJS 做請求轉發,現在服務端直接把請求地址告訴瀏覽器了,瀏覽器就會直接去訪問 http://localhost:8081/login 了,而不會做請求轉發了,因此就發生了跨域問題。

解決方案

很明顯,上面的問題我們不能用跨域的思路來解決,雖然這種方式看起來也能解決問題,但不是最佳方案。

如果我們的 Spring Security 在用戶未獲認證的時候去請求一個需要認證后才能請求的數據,此時不給用戶重定向,而是直接就返回一個 JSON,告訴用戶這個請求需要認證之后才能發起,就不會有上面的事情了。

這里就涉及到 Spring Security 中的一個接口 AuthenticationEntryPoint,該接口有一個實現類:LoginUrlAuthenticationEntryPoint ,該類中有一個方法 commence,如下:

/**
 * Performs the redirect (or forward) to the login form URL.
 */
public void commence(HttpServletRequest request, HttpServletResponse response,
		AuthenticationException authException) {
	String redirectUrl = null;
	if (useForward) {
		if (forceHttps && "http".equals(request.getScheme())) {
			redirectUrl = buildHttpsRedirectUrlForRequest(request);
		}
		if (redirectUrl == null) {
			String loginForm = determineUrlToUseForThisRequest(request, response,
					authException);
			if (logger.isDebugEnabled()) {
				logger.debug("Server side forward to: " + loginForm);
			}
			RequestDispatcher dispatcher = request.getRequestDispatcher(loginForm);
			dispatcher.forward(request, response);
			return;
		}
	}
	else {
		redirectUrl = buildRedirectUrlToLoginPage(request, response, authException);
	}
	redirectStrategy.sendRedirect(request, response, redirectUrl);
}

首先我們從這個方法的注釋中就可以看出,這個方法是用來決定到底是要重定向還是要 forward,通過 Debug 追蹤,我們發現默認情況下 useForward 的值為 false,所以請求走進了重定向。

那么我們解決問題的思路很簡單,直接重寫這個方法,在方法中返回 JSON 即可,不再做重定向操作,具體配置如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
 http.authorizeRequests()
 .anyRequest().authenticated()
 .formLogin()
 .loginProcessingUrl("/doLogin")
 .loginPage("/login")
 //其他配置
 .permitAll()
 .and()
 .csrf().disable().exceptionHandling()
 .authenticationEntryPoint(new AuthenticationEntryPoint() {
 @Override
 public void commence(HttpServletRequest req, HttpServletResponse resp, AuthenticationException authException) throws IOException, ServletException {
 resp.setContentType("application/json;charset=utf-8");
 PrintWriter out = resp.getWriter();
 RespBean respBean = RespBean.error("訪問失敗!");
 if (authException instanceof InsufficientAuthenticationException) {
 respBean.setMsg("請求失敗,請聯系管理員!");
 }
 out.write(new ObjectMapper().writeValueAsString(respBean));
 out.flush();
 out.close();
 }
 });
}

在 Spring Security 的配置中加上自定義的 AuthenticationEntryPoint 處理方法,該方法中直接返回相應的 JSON 提示即可。這樣,如果用戶再去直接訪問一個需要認證之后才可以訪問的請求,就不會發生重定向操作了,服務端會直接給瀏覽器一個 JSON 提示,瀏覽器收到 JSON 之后,該干嘛干嘛。

結語

好了,一個小小的重定向問題和小伙伴們分享下,不知道大家有沒有看懂呢?

分享到:
標簽:Spring Security
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定