SpringSecurity?表單登錄的實(shí)現(xiàn)
表單登錄
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/mylogin.html")
.loginProcessingUrl("/doLogin")
.defaultSuccessUrl("/index.html")
.failureHandler(new MyAuthenticationFailureHandler())
.usernameParameter("uname")
.passwordParameter("passwd")
.permitAll()
.and()
.logout()
.logoutRequestMatcher(new OrRequestMatcher(
new AntPathRequestMatcher("/logout1", "GET"),
new AntPathRequestMatcher("/logout2", "POST")))
.invalidateHttpSession(true)
.clearAuthentication(true)
.defaultLogoutSuccessHandlerFor((req,resp,auth)->{
resp.setContentType("application/json;charset=utf-8");
Map<String, Object> result = new HashMap<>();
result.put("status", 200);
result.put("msg", "使用 logout1 注銷成功!");
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(result);
resp.getWriter().write(s);
},new AntPathRequestMatcher("/logout1","GET"))
.defaultLogoutSuccessHandlerFor((req,resp,auth)->{
resp.setContentType("application/json;charset=utf-8");
Map<String, Object> result = new HashMap<>();
result.put("status", 200);
result.put("msg", "使用 logout2 注銷成功!");
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(result);
resp.getWriter().write(s);
},new AntPathRequestMatcher("/logout2","POST"))
.and()
.csrf().disable();
}
}
springSecurity需要自定義配置值 基本都是繼承WebSecurityConfigurerAdapter
- authorizeRequests表示開啟權(quán)限配置,.anyRequest().authenticated()表示所有的請(qǐng)求都認(rèn)證之后才能訪問
- and()方法返回HttpSecurity的實(shí)例
- formLogin()表示開啟表單登錄配置
- loginPage 配置登錄頁面地址
- loginProcessingUrl 配置登錄接口地址
- defaultSuccessUrl 登錄成功后的跳轉(zhuǎn)地址
- failureUrl表示登錄失敗后的跳轉(zhuǎn)地址
- usernameParameter表示登錄用戶名的參數(shù)名
- passwordParameter 登錄mima的參數(shù)名
- permitAll()表示和登錄相關(guān)的頁面和接口不做攔截 直接通過
其中l(wèi)oginProcessingUrl usernameParameter passwordParameter要和登錄表單的配置一致。
.loginPage("/mylogin.html") //
.loginProcessingUrl("/doLogin")
.defaultSuccessUrl("/index.html")
.failureHandler(new MyAuthenticationFailureHandler())
.usernameParameter("uname")
.passwordParameter("passwd")
csrf().disable()表示禁用CSRF防御功能
登錄成功
用戶登錄成功后除了defaultSuccessUrl方法可以實(shí)現(xiàn)登錄成功的跳轉(zhuǎn)之外,successForwardUrl也可以實(shí)現(xiàn)登錄成功后的跳轉(zhuǎn),
defaultSuccessUrl 和successForwardUrl區(qū)別:
- defaultSuccessUrl表示當(dāng)用戶登錄成功后,會(huì)自動(dòng)重定向到登錄之前的地址,如果用戶本身就是訪問的登錄頁面,登錄成功后就會(huì)重定向到defaultSuccessUrl指定頁面
- successForwardUrl不會(huì)考慮用戶之前的訪問地址,登錄成功后通過服務(wù)器端跳轉(zhuǎn)到successForwardUrl所指定的頁面。
defaultSuccessUrl是客戶端跳轉(zhuǎn)重定向,successForwardUrl是通過服務(wù)端實(shí)現(xiàn)的跳轉(zhuǎn)。
他們的接口都AuthenticationSuccessHandler
AuthenticationSuccessHandler有三個(gè)實(shí)現(xiàn)類
SimpleUrlAuthenticationSuccessHandler 繼承 AbstractAuthenticationTargetUrlRequestHandler 通過他的handle方法處理請(qǐng)求
SavedRequestAwareAuthenticationSuccessHandler 在SimpleUrlAuthenticationSuccessHandler基礎(chǔ)上增加了請(qǐng)求加緩存的功能,可以記錄之前請(qǐng)求的地址,今兒在登錄成功后重定向到開始訪問的地址。
ForwardAuthenticationSuccessHandler 是服務(wù)端的跳轉(zhuǎn)
SavedRequestAwareAuthenticationSuccessHandler
defaultSuccessUrl 對(duì)應(yīng)的是SavedRequestAwareAuthenticationSuccessHandler
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
SavedRequest savedRequest = this.requestCache.getRequest(request, response);
if (savedRequest == null) {
super.onAuthenticationSuccess(request, response, authentication);
} else {
String targetUrlParameter = this.getTargetUrlParameter();
if (!this.isAlwaysUseDefaultTargetUrl() && (targetUrlParameter == null || !StringUtils.hasText(request.getParameter(targetUrlParameter)))) {
this.clearAuthenticationAttributes(request);
String targetUrl = savedRequest.getRedirectUrl();
this.logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
this.getRedirectStrategy().sendRedirect(request, response, targetUrl);
} else {
this.requestCache.removeRequest(request, response);
super.onAuthenticationSuccess(request, response, authentication);
}
}
}
- 首先從requestCache中獲取緩存下來的請(qǐng)求 如果沒有獲取到緩存請(qǐng)求,就說明用戶在訪問登錄頁面之前并沒有訪問其他頁面,此時(shí)直接調(diào)用父類的onAuthenticationSuccess方法來處理,重定向到defaultSuccessUrl指定的地址。
- 獲取targetUrlParameter 拿到target參數(shù)后重定向地址。
- 如果targetUrlParameter不存在或者alwaysUseDefaultTargetUrl為true 緩存下來的請(qǐng)求沒有意義,直接調(diào)用父類的onAuthenticationSuccess方法完成重定向 。targetUrlParameter存在 則重定向到targetUrlParameter中,alwaysUseDefaultTargetUrl為true 走默認(rèn)
ForwardAuthenticationSuccessHandler
successForwardUrl對(duì)應(yīng)ForwardAuthenticationSuccessHandler
public class ForwardAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private final String forwardUrl;
public ForwardAuthenticationSuccessHandler(String forwardUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(forwardUrl), () -> {
return "'" + forwardUrl + "' is not a valid forward URL";
});
this.forwardUrl = forwardUrl;
}
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
request.getRequestDispatcher(this.forwardUrl).forward(request, response);
}
}
主要調(diào)用getRequestDispatcher進(jìn)行服務(wù)端請(qǐng)求轉(zhuǎn)發(fā)
自定義AuthenticationSuccessHandler 實(shí)現(xiàn)類
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler{
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
Map<String, Object> resp = new HashMap<>();
resp.put("status", 200);
resp.put("msg", "登錄成功!");
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(resp);
response.getWriter().write(s);
}
}
.successHandler(new MyAuthenticationSuccessHandler())
通過HttpServletResponse對(duì)象返回登錄成功的json給前端
登錄失敗
failureUrl表示登錄失敗后的重定向到配置的頁面,重定向是客戶端的跳轉(zhuǎn),不方便攜帶請(qǐng)求失敗的異常信息。
failureForwardUrl是服務(wù)端的跳轉(zhuǎn),可以攜帶登錄異常信息。登錄失敗,自動(dòng)跳轉(zhuǎn)回登錄頁面,將錯(cuò)誤信息展示出來。
他們的配置的是AuthenticationFailureHandler接口的實(shí)現(xiàn)類
SimpleUrlAuthenticationFailureHandler
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.springframework.security.web.authentication;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert;
public class SimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler {
protected final Log logger = LogFactory.getLog(this.getClass());
private String defaultFailureUrl;
private boolean forwardToDestination = false;
private boolean allowSessionCreation = true;
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
public SimpleUrlAuthenticationFailureHandler() {
}
public SimpleUrlAuthenticationFailureHandler(String defaultFailureUrl) {
this.setDefaultFailureUrl(defaultFailureUrl);
}
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
if (this.defaultFailureUrl == null) {
this.logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
} else {
this.saveException(request, exception);
if (this.forwardToDestination) {
this.logger.debug("Forwarding to " + this.defaultFailureUrl);
request.getRequestDispatcher(this.defaultFailureUrl).forward(request, response);
} else {
this.logger.debug("Redirecting to " + this.defaultFailureUrl);
this.redirectStrategy.sendRedirect(request, response, this.defaultFailureUrl);
}
}
}
protected final void saveException(HttpServletRequest request, AuthenticationException exception) {
if (this.forwardToDestination) {
request.setAttribute("SPRING_SECURITY_LAST_EXCEPTION", exception);
} else {
HttpSession session = request.getSession(false);
if (session != null || this.allowSessionCreation) {
request.getSession().setAttribute("SPRING_SECURITY_LAST_EXCEPTION", exception);
}
}
}
}
當(dāng)用戶構(gòu)造SimpleUrlAuthenticationFailureHandler對(duì)象時(shí)候傳入defaultFailureUrl,也就是登錄失敗時(shí)要跳轉(zhuǎn)的url。在onAuthenticationFailure方法中
- 如果defaultFailureUrl為null,直接通過response返回異常信息,否則調(diào)用saveException
- saveException 如果forwardToDestination為true,表示通過服務(wù)器端跳轉(zhuǎn)回到登錄頁面,此時(shí)就把異常信息放到request中。
- 回到onAuthenticationFailure方法,如果forwardToDestination為true,就通過服務(wù)器端跳回到登錄頁面,否則重定向到登錄頁面。
自定義AuthenticationFailureHandler實(shí)現(xiàn)類
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
Map<String, Object> resp = new HashMap<>();
resp.put("status", 500);
resp.put("msg", "登錄失敗!" + exception.getMessage());
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(resp);
response.getWriter().write(s);
}
}
通過HttpServletResponse對(duì)象返回登錄失敗的json給前端
注銷登錄
.logout()
.logoutUrl("")
.logoutRequestMatcher(new OrRequestMatcher(
new AntPathRequestMatcher("/logout1", "GET"),
new AntPathRequestMatcher("/logout2", "POST")))
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("")
- logout() 表示開啟注銷登錄配置。
- logoutUrl 指定注銷登錄請(qǐng)求地址,默認(rèn)GET請(qǐng)求,路徑logout
- invalidateHttpSession 表示是否使session失效,默認(rèn)為true
- clearAuthentication 表示是否清除認(rèn)證信息,默認(rèn)為true
- logoutSuccessUrl 表示注銷登錄后的跳轉(zhuǎn)地址。
- logoutRequestMatcher 匹配多個(gè)注銷登錄
自定義注銷成功的返回內(nèi)容
.logout()
.logoutRequestMatcher(new OrRequestMatcher(
new AntPathRequestMatcher("/logout1", "GET"),
new AntPathRequestMatcher("/logout2", "POST")))
.invalidateHttpSession(true)
.clearAuthentication(true)
.defaultLogoutSuccessHandlerFor((req,resp,auth)->{
resp.setContentType("application/json;charset=utf-8");
Map<String, Object> result = new HashMap<>();
result.put("status", 200);
result.put("msg", "使用 logout1 注銷成功!");
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(result);
resp.getWriter().write(s);
},new AntPathRequestMatcher("/logout1","GET"))
.defaultLogoutSuccessHandlerFor((req,resp,auth)->{
resp.setContentType("application/json;charset=utf-8");
Map<String, Object> result = new HashMap<>();
result.put("status", 200);
result.put("msg", "使用 logout2 注銷成功!");
ObjectMapper om = new ObjectMapper();
String s = om.writeValueAsString(result);
resp.getWriter().write(s);
},new AntPathRequestMatcher("/logout2","POST"))
.and()
.csrf().disable();
defaultLogoutSuccessHandlerFor()兩個(gè)參數(shù) 第一個(gè)是注銷成功的回調(diào),第二個(gè)是具體的注銷請(qǐng)求。
到此這篇關(guān)于SpringSecurity 表單登錄的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)SpringSecurity 表單登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringSecurity表單配置之登錄成功及頁面跳轉(zhuǎn)原理解析
- Spring?Security登錄表單配置示例詳解
- SpringBoot基于SpringSecurity表單登錄和權(quán)限驗(yàn)證的示例
- SpringSecurity 自定義表單登錄的實(shí)現(xiàn)
- SpringSecurity 默認(rèn)表單登錄頁展示流程源碼
- Spring Security 表單登錄功能的實(shí)現(xiàn)方法
- Spring Security在標(biāo)準(zhǔn)登錄表單中添加一個(gè)額外的字段
- 最新Spring?Security實(shí)戰(zhàn)教程之表單登錄定制到處理邏輯的深度改造(最新推薦)
相關(guān)文章
springmvc+spring+mybatis實(shí)現(xiàn)用戶登錄功能(下)
這篇文章主要為大家詳細(xì)介紹了springmvc+spring+mybatis實(shí)現(xiàn)用戶登錄功能的第二篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Java實(shí)現(xiàn)字符串的分割(基于String.split()方法)
Java中的我們可以利用split把字符串按照指定的分割符進(jìn)行分割,然后返回字符串?dāng)?shù)組,下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)字符串的分割的相關(guān)資料,是基于jDK1.8版本中的String.split()方法,需要的朋友可以參考下2022-09-09
基于SpringBoot和Vue的動(dòng)態(tài)語音播放實(shí)現(xiàn)
本文介紹如何使用SpringBoot和Vue實(shí)現(xiàn)音頻文件的動(dòng)態(tài)播放,包括前端頁面設(shè)計(jì)、后端接口開發(fā)、音頻文件存儲(chǔ)和調(diào)用等方面。通過該實(shí)現(xiàn),用戶可以在網(wǎng)頁上直接播放音頻,增強(qiáng)用戶體驗(yàn),提高網(wǎng)站互動(dòng)性2023-04-04
將RestTemplate的編碼格式改為UTF-8,防止亂碼問題
這篇文章主要介紹了將RestTemplate的編碼格式改為UTF-8,防止亂碼問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
Java實(shí)現(xiàn)電影院訂票系統(tǒng)代碼
這篇文章主要介紹了Java實(shí)現(xiàn)電影院訂票系統(tǒng)代碼,代碼實(shí)現(xiàn)了界面類登錄注冊(cè)類,用戶類等,具有一定參考價(jià)值,需要的朋友可以參考下。2017-11-11

