最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringSecurity自定義Form表單使用方法講解

 更新時(shí)間:2023年01月17日 09:51:25   作者:做網(wǎng)安的小王  
這篇文章主要介紹了Spring Security自定義Form表單使用方法,雖然 Spring Security 提供了默認(rèn)的登錄表單,實(shí)際項(xiàng)目里肯定是不可以直接使用的,當(dāng)然 Spring Security 也提供了自定義登錄表單的功能

背景

本系列教程,是作為團(tuán)隊(duì)內(nèi)部的培訓(xùn)資料準(zhǔn)備的。主要以實(shí)驗(yàn)的方式來體驗(yàn)SpringSecurity的各項(xiàng)Feature。

新建一個SpringBoot項(xiàng)目,起名springboot-security-form,核心依賴為Web,SpringSecurityThymeleaf。

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>
</dependencies> 

實(shí)驗(yàn)-HttpBasic

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {// There is no PasswordEncoder mapped for the id "null"PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();String yourPassword = "123";System.out.println("Encoded password: " + encoder.encode(yourPassword));// Config account info and permissionsauth.inMemoryAuthentication().withUser("dev").password(encoder.encode(yourPassword)).authorities("p1").and().withUser("test").password(encoder.encode(yourPassword)).authorities("p2");
}
@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/user/add").hasAuthority("p1").antMatchers("/user/query").hasAuthority("p2").antMatchers("/user/**").authenticated().anyRequest().permitAll() // Let other request pass.and().httpBasic();
} 

實(shí)驗(yàn)-自定義登錄頁面

登錄頁面配置

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/user/add").hasAuthority("p1").antMatchers("/user/query").hasAuthority("p2").antMatchers("/user/**").authenticated().anyRequest().permitAll() // Let other request pass.and().csrf().disable() // turn off csrf, or will be 403 forbidden.formLogin() // Support form and HTTPBasic.loginPage("/login");
} 

后端登錄頁面接口

@Controller
public class LoginController {@GetMapping("/login")public String login() {return "login";}@GetMapping(value = "/user/add")@ResponseBodypublic String accessResource1() {return " Access Resource 1: Add User";}@GetMapping(value = "/user/query")@ResponseBodypublic String accessResource2() {return " Access Resource 2: Query User";}
} 

前端模板

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Login</title>
</head>
<body>
<form action="login" method="post"><span>用戶名</span><input type="text" name="username" /> <br><span>密碼</span><input type="password" name="password" /> <br><input type="submit" value="登錄">
</form>
</body>
</html> 

Note:此時(shí),需要先關(guān)閉CSRF,.csrf().disable(),否則報(bào)403;

實(shí)驗(yàn)-自定義登錄接口

默認(rèn)登錄頁面接口與登錄數(shù)據(jù)提交接口是同一個:/login,順著.loginPage,進(jìn)入FormLoginConfigurer,源碼如下:

@Override
public FormLoginConfigurer<H> loginPage(String loginPage) {return super.loginPage(loginPage);
} 

繼續(xù)進(jìn)入父類的loginPage方法,

protected T loginPage(String loginPage) {setLoginPage(loginPage);updateAuthenticationDefaults();this.customLoginPage = true;return getSelf();
} 

繼續(xù)跟蹤進(jìn)入方法updateAuthenticationDefaults();,可以看到,如果沒有配置loginProcessingUrl,那么loginProcessingUrlloginPage便相同。

protected final void updateAuthenticationDefaults() {if (loginProcessingUrl == null) {loginProcessingUrl(loginPage);}if (failureHandler == null) {failureUrl(loginPage + "?error");}final LogoutConfigurer<B> logoutConfigurer = getBuilder().getConfigurer(LogoutConfigurer.class);if (logoutConfigurer != null && !logoutConfigurer.isCustomLogoutSuccess()) {logoutConfigurer.logoutSuccessUrl(loginPage + "?logout");}
} 

下面我們自定義登錄數(shù)據(jù)提交接口為/formLogin,此時(shí)相應(yīng)的前端action也要修改。

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/user/add").hasAuthority("p1").antMatchers("/user/query").hasAuthority("p2").antMatchers("/user/**").authenticated().anyRequest().permitAll() // Let other request pass.and().csrf().disable() // turn off csrf, or will be 403 forbidden.formLogin() // Support form and HTTPBasic.loginPage("/login").loginProcessingUrl("/formLogin");
} 
<form action="formLogin" method="post"><span>用戶名</span><input type="text" name="username" /> <br><span>密碼</span><input type="password" name="password" /> <br><input type="submit" value="登錄">
</form> 

實(shí)驗(yàn)-自定義登錄數(shù)據(jù)參數(shù)

前面我們自定義了登錄頁面,在form表單中設(shè)置用戶名、密碼分別為username, password,那為什么這樣寫呢,可以改成別的嘛?可以倒是可以,但是不能隨便改;

如果這里我們把username改為name,再次嘗試登錄,后端接口將報(bào)錯:org.springframework.security.authentication.BadCredentialsException: Bad credentials。。可是實(shí)際項(xiàng)目中我們的用戶名密碼就是不叫這個名字呢?我們可以進(jìn)行配置.usernameParameter("name")

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/user/add").hasAuthority("p1").antMatchers("/user/query").hasAuthority("p2").antMatchers("/user/**").authenticated().anyRequest().permitAll() // Let other request pass.and().csrf().disable() // turn off csrf, or will be 403 forbidden.formLogin() // Support form and HTTPBasic.loginPage("/login").loginProcessingUrl("/formLogin").usernameParameter("name");
} 
<form action="formLogin" method="post"><span>用戶名</span><input type="text" name="name" /> <br><span>密碼</span><input type="password" name="password" /> <br><input type="submit" value="登錄">
</form> 

默認(rèn)的用戶名、密碼分別為username, password,我們看下SpringSecurity的源碼:

public final class FormLoginConfigurer<H extends HttpSecurityBuilder<H>> extends
		AbstractAuthenticationFilterConfigurer<H, FormLoginConfigurer<H>, UsernamePasswordAuthenticationFilter> {
	/**
	 * Creates a new instance
	 * @see HttpSecurity#formLogin()
	 */
	public FormLoginConfigurer() {
		super(new UsernamePasswordAuthenticationFilter(), null);
		usernameParameter("username");
		passwordParameter("password");
	}
} 

實(shí)驗(yàn)-自定義登錄失敗、成功處理器

問題:就以上個實(shí)驗(yàn)3中的報(bào)錯信息為例,或當(dāng)用戶名、密碼輸錯后,如何在后臺看到錯誤信息?

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/user/add").hasAuthority("p1").antMatchers("/user/query").hasAuthority("p2").antMatchers("/user/**").authenticated().anyRequest().permitAll() // Let other request pass.and().csrf().disable() // turn off csrf, or will be 403 forbidden.formLogin() // Support form and HTTPBasic.loginPage("/login").loginProcessingUrl("/formLogin").usernameParameter("name").failureHandler(new AuthenticationFailureHandler(){@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {exception.printStackTrace();request.getRequestDispatcher(request.getRequestURL().toString()).forward(request, response);}});
} 

常見的認(rèn)證異常,這里可以看到AuthenticationException共有18個子類:

上述增加了在認(rèn)證失敗時(shí)的處理:輸出錯誤信息。同理,如果想在登錄成功時(shí)直接進(jìn)行一些處理(eg: 數(shù)據(jù)初始化等),可以使用以下配置:

.successHandler(new AuthenticationSuccessHandler() {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication) throws IOException, ServletException {System.out.println("Login Successfully~");// do something here: initial work or forward to different url regarding different roles...request.getRequestDispatcher("").forward(request, response);}
}) 

實(shí)驗(yàn)-自定義登錄成功跳轉(zhuǎn)頁面

經(jīng)歷千難萬險(xiǎn),終于要登錄成功了。進(jìn)來之后要跳轉(zhuǎn)到哪里呢?看你嘍~想跳哪里跳哪里。。

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/user/add").hasAuthority("p1").antMatchers("/user/query").hasAuthority("p2").antMatchers("/user/**").authenticated().anyRequest().permitAll() // Let other request pass.and().csrf().disable() // turn off csrf, or will be 403 forbidden.formLogin() // Support form and HTTPBasic.loginPage("/login").loginProcessingUrl("/formLogin").usernameParameter("name").failureHandler(new AuthenticationFailureHandler(){@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {exception.printStackTrace();request.getRequestDispatcher(request.getRequestURL().toString()).forward(request, response);}}).successForwardUrl("/ok"); // custom login success page, a POST request
} 
@Controller
public class LoginController {...@PostMapping(value = "/ok")@ResponseBodypublic String ok() {return "ok";}
} 

通過.successForwardUrl("/ok")配置了登錄成功之后要跳轉(zhuǎn)的頁面路徑或接口,同時(shí)需要在后端新增/ok接口。

Note:

  • 注意這里successForwardUrl的接口必須為POST接口;
  • 除了.successForwardUrl("/ok");,還可以使用.defaultSuccessUrl("/ok");或者.defaultSuccessUrl("/ok", true); 第二個參數(shù)true表示不管是從哪個地址進(jìn)來,登錄后全部跳轉(zhuǎn)到指定的地址,此時(shí)與successForwardUrl效果相同,默認(rèn)為false
  • 當(dāng)然,除了登錄成功后的跳轉(zhuǎn),還有登錄失敗后的跳轉(zhuǎn):failureForwardUrl

實(shí)驗(yàn)-自定義退出接口

默認(rèn)的退出接口是/logout,可進(jìn)行配置:

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/user/add").hasAuthority("p1").antMatchers("/user/query").hasAuthority("p2").antMatchers("/user/**").authenticated().anyRequest().permitAll() // Let other request pass.and().csrf().disable() // turn off csrf, or will be 403 forbidden.formLogin() // Support form and HTTPBasic.loginPage("/login").loginProcessingUrl("/formLogin").usernameParameter("name").failureHandler(new AuthenticationFailureHandler(){@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {exception.printStackTrace();request.getRequestDispatcher(request.getRequestURL().toString()).forward(request, response);}}).successForwardUrl("/ok") // custom login success page, a POST request.and().logout().logoutUrl("/leave");} 

上述配置將退出接口改為/leave。在默認(rèn)的退出過程中,還做了諸如清除認(rèn)證信息和使Session失效等工作:

public class SecurityContextLogoutHandler implements LogoutHandler {
	protected final Log logger = LogFactory.getLog(this.getClass());
	private boolean invalidateHttpSession = true;
	private boolean clearAuthentication = true;
	// ~ Methods
	// ==========================================
	/**
	 * Requires the request to be passed in.
	 *
	 * @param request from which to obtain a HTTP session (cannot be null)
	 * @param response not used (can be <code>null</code>)
	 * @param authentication not used (can be <code>null</code>)
	 */
	public void logout(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) {
		Assert.notNull(request, "HttpServletRequest required");
		if (invalidateHttpSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				logger.debug("Invalidating session: " + session.getId());
				session.invalidate();
			}
		}
		if (clearAuthentication) {
			SecurityContext context = SecurityContextHolder.getContext();
			context.setAuthentication(null);
		}
		SecurityContextHolder.clearContext();
	}
} 

到此這篇關(guān)于SpringSecurity自定義Form表單使用方法講解的文章就介紹到這了,更多相關(guān)SpringSecurity Form表單內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java的Object類九個方法技巧

    Java的Object類九個方法技巧

    這篇文章主要介紹了Java的Object類九個方法技巧,Java的Object?類的完整路徑是java.lang.Object?,是所有類的父類編譯,下文相關(guān)資料,需要的朋友可以參考一下
    2022-04-04
  • Javaweb EL自定義函數(shù)開發(fā)及代碼實(shí)例

    Javaweb EL自定義函數(shù)開發(fā)及代碼實(shí)例

    這篇文章主要介紹了Javaweb EL自定義函數(shù)開發(fā)及代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Java原子操作CAS原理解析

    Java原子操作CAS原理解析

    這篇文章主要介紹了Java原子操作CAS原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • Spring + mybatis + mysql使用事物的幾種方法總結(jié)

    Spring + mybatis + mysql使用事物的幾種方法總結(jié)

    這篇文章主要給大家總結(jié)介紹了關(guān)于Spring + mybatis + mysql使用事物的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • mybatis-spring:@MapperScan注解的使用

    mybatis-spring:@MapperScan注解的使用

    這篇文章主要介紹了mybatis-spring:@MapperScan注解的使用,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 使用Java操作TensorFlow的方法

    使用Java操作TensorFlow的方法

    TensorFlow是一個功能強(qiáng)大且廣泛使用的框架,它不斷得到改進(jìn),并最近被引入新語言包括Java和JavaScript,這篇文章主要介紹了如何使用Java操作TensorFlow,需要的朋友可以參考下
    2023-05-05
  • java中BigDecimal和0比較的示例代碼

    java中BigDecimal和0比較的示例代碼

    這篇文章主要介紹了java中BigDecimal和0比較的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • arthas在idea和docker中的應(yīng)用方式

    arthas在idea和docker中的應(yīng)用方式

    這篇文章主要介紹了arthas在idea和docker中的應(yīng)用方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-10-10
  • Java使用Canal同步MySQL數(shù)據(jù)到Redis

    Java使用Canal同步MySQL數(shù)據(jù)到Redis

    在現(xiàn)代微服務(wù)架構(gòu)中,數(shù)據(jù)同步是一個常見的需求,特別是將?MySQL?數(shù)據(jù)實(shí)時(shí)同步到?Redis,下面我們就來看看Java如何使用Canal同步MySQL數(shù)據(jù)到Redis吧
    2024-11-11
  • Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之排序算法

    Java 數(shù)據(jù)結(jié)構(gòu)與算法系列精講之排序算法

    排序算法是《數(shù)據(jù)結(jié)構(gòu)與算法》中最基本的算法之一。排序算法可以分為內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部的排序記錄,在排序過程中需要訪問外存
    2022-02-02

最新評論

博白县| 娱乐| 禹州市| 瑞金市| 定边县| 乐平市| 永济市| 玛曲县| 津市市| 咸宁市| 抚远县| 鸡东县| 缙云县| 抚宁县| 延长县| 武城县| 台湾省| 沈阳市| 盈江县| 德兴市| 连云港市| 东至县| 成都市| 泗洪县| 微山县| 博湖县| 行唐县| 沁源县| 泰和县| 沈丘县| 临高县| 娱乐| 遵化市| 大名县| 蒲江县| 郧西县| 石台县| 扬中市| 霸州市| 纳雍县| 运城市|