日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Security在标准登录表单中添加一个额外的字段

發布時間:2023/12/10 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Security在标准登录表单中添加一个额外的字段 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

在本文中,我們將通過向標準登錄表單添加額外字段來實現Spring Security的自定義身份驗證方案

我們將重點關注兩種不同的方法,以展示框架的多功能性以及我們可以使用它的靈活方式

我們的第一種方法是一個簡單的解決方案,專注于重用現有的核心Spring Security實現

我們的第二種方法是更加定制的解決方案,可能更適合高級用例。

2. Maven設置

我們將使用Spring Boot啟動程序來引導我們的項目并引入所有必需的依賴項。
我們將使用的設置需要父聲明,Web啟動器和安全啟動器;我們還將包括thymeleaf :

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.0.M7</version><relativePath/> </parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.thymeleaf.extras</groupId><artifactId>thymeleaf-extras-springsecurity4</artifactId></dependency> </dependencies>

可以在Maven Central找到最新版本的Spring Boot安全啟動器。

3.簡單的項目設置

在我們的第一種方法中,我們將專注于重用Spring Security提供的實現。特別是,我們將重用DaoAuthenticationProvider和UsernamePasswordToken,因為它們是“開箱即用”的

關鍵組件包括:
  • SimpleAuthenticationFilter - UsernamePasswordAuthenticationFilter的擴展
  • SimpleUserDetailsService - UserDetailsService的實現
  • User - Spring Security提供的User類的擴展,它聲明了我們的額外域字段
  • SecurityConfig - 我們的Spring Security配置,它將SimpleAuthenticationFilter插入到過濾器鏈中,聲明安全規則并連接依賴項
  • login.html - 收集用戶名,密碼和域的登錄頁面

3.1. 簡單Authentication Filter

在我們的SimpleAuthenticationFilter中,域和用戶名字段是從請求中提取的。我們連接這些值并使用它們來創建UsernamePasswordAuthenticationToken的實例。

然后將令牌傳遞給AuthenticationProvider進行身份驗證:

public class SimpleAuthenticationFilterextends UsernamePasswordAuthenticationFilter {@Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {// ...UsernamePasswordAuthenticationToken authRequest= getAuthRequest(request);setDetails(request, authRequest);return this.getAuthenticationManager().authenticate(authRequest);}private UsernamePasswordAuthenticationToken getAuthRequest(HttpServletRequest request) {String username = obtainUsername(request);String password = obtainPassword(request);String domain = obtainDomain(request);// ...String usernameDomain = String.format("%s%s%s", username.trim(), String.valueOf(Character.LINE_SEPARATOR), domain);return new UsernamePasswordAuthenticationToken(usernameDomain, password);}// other methods }

3.2.簡單的UserDetails服務

UserDetailsService定義了一個名為loadUserByUsername的方法。我們的實現提取用戶名和域名。然后將值傳遞給我們的UserRepository以獲取用戶:

public class SimpleUserDetailsService implements UserDetailsService {// ...@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {String[] usernameAndDomain = StringUtils.split(username, String.valueOf(Character.LINE_SEPARATOR));if (usernameAndDomain == null || usernameAndDomain.length != 2) {throw new UsernameNotFoundException("Username and domain must be provided");}User user = userRepository.findUser(usernameAndDomain[0], usernameAndDomain[1]);if (user == null) {throw new UsernameNotFoundException(String.format("Username not found for domain, username=%s, domain=%s", usernameAndDomain[0], usernameAndDomain[1]));}return user;} }

3.3. Spring Security配置

我們的設置與標準的Spring Security配置不同,因為我們在默認情況下通過調用addFilterBefore將SimpleAuthenticationFilter插入到過濾器鏈中:

@Override protected void configure(HttpSecurity http) throws Exception {http.addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class).authorizeRequests().antMatchers("/css/**", "/index").permitAll().antMatchers("/user/**").authenticated().and().formLogin().loginPage("/login").and().logout().logoutUrl("/logout"); }

我們可以使用提供的DaoAuthenticationProvider,因為我們使用SimpleUserDetailsService配置它。回想一下,我們的SimpleUserDetailsService知道如何解析我們的用戶名和域字段,并返回在驗證時使用的相應用戶。

public AuthenticationProvider authProvider() {DaoAuthenticationProvider provider = new DaoAuthenticationProvider();provider.setUserDetailsService(userDetailsService);provider.setPasswordEncoder(passwordEncoder());return provider; }

由于我們使用的是SimpleAuthenticationFilter,因此我們配置自己的AuthenticationFailureHandler以確保正確處理失敗的登錄嘗試:

public SimpleAuthenticationFilter authenticationFilter() throws Exception {SimpleAuthenticationFilter filter = new SimpleAuthenticationFilter();filter.setAuthenticationManager(authenticationManagerBean());filter.setAuthenticationFailureHandler(failureHandler());return filter; }

3.4.登錄頁面

我們使用的登錄頁面收集我們的SimpleAuthenticationFilter提取的額外的字段:

<form class="form-signin" th:action="@{/login}" method="post"><h2 class="form-signin-heading">Please sign in</h2><p>Example: user / domain / password</p><p th:if="${param.error}" class="error">Invalid user, password, or domain</p><p><label for="username" class="sr-only">Username</label><input type="text" id="username" name="username" class="form-control"placeholder="Username" required autofocus/></p><p><label for="domain" class="sr-only">Domain</label><input type="text" id="domain" name="domain" class="form-control"placeholder="Domain" required autofocus/></p><p><label for="password" class="sr-only">Password</label><input type="password" id="password" name="password" class="form-control"placeholder="Password" required autofocus/></p><button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button><br/><p><a href="/index" th:href="@{/index}">Back to home page</a></p> </form>

當我們運行應用程序并訪問http:// localhost:8081上下文時,我們會看到一個訪問安全頁面的鏈接。單擊該鏈接將顯示登錄頁面。正如所料,我們看到了額外的域名字段

3.5.總結

在我們的第一個例子中,我們能夠通過“偽造”用戶名字段來重用DaoAuthenticationProvider和UsernamePasswordAuthenticationToken

因此,我們能夠使用最少量的配置和其他代碼添加對額外登錄字段的支持

4.自定義項目設置

我們的第二種方法與第一種方法非常相似,但可能更適合于非平凡用例。

我們的第二種方法的關鍵組成部分包括:

  • CustomAuthenticationFilter - UsernamePasswordAuthenticationFilter的擴展
  • CustomUserDetailsService - 聲明loadUserbyUsernameAndDomain方法的自定義接口
  • CustomUserDetailsServiceImpl - CustomUserDetailsService的實現
  • CustomUserDetailsAuthenticationProvider - AbstractUserDetailsAuthenticationProvider的擴展
  • CustomAuthenticationToken - UsernamePasswordAuthenticationToken的擴展
  • User - Spring Security提供的User類的擴展,它聲明了我們的額外域字段
  • SecurityConfig - 我們的Spring Security配置,它將CustomAuthenticationFilter插入到過濾器鏈中,聲明安全規則并連接依賴項
  • login.html - 收集用戶名,密碼和域的登錄頁面

4.1.自定義驗證過濾器

在我們的CustomAuthenticationFilter中,我們從請求中提取用戶名,密碼和域字段。這些值用于創建CustomAuthenticationToken的實例,該實例將傳遞給AuthenticationProvider進行身份驗證:

public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {public static final String SPRING_SECURITY_FORM_DOMAIN_KEY = "domain";@Overridepublic Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse response) throws AuthenticationException {// ...CustomAuthenticationToken authRequest = getAuthRequest(request);setDetails(request, authRequest);return this.getAuthenticationManager().authenticate(authRequest);}private CustomAuthenticationToken getAuthRequest(HttpServletRequest request) {String username = obtainUsername(request);String password = obtainPassword(request);String domain = obtainDomain(request);// ...return new CustomAuthenticationToken(username, password, domain);}

4.2.自定義UserDetails服務

我們的CustomUserDetailsService合約定義了一個名為loadUserByUsernameAndDomain的方法。

們創建的CustomUserDetailsServiceImpl類只是實現并委托我們的CustomUserRepository來獲取用戶

public UserDetails loadUserByUsernameAndDomain(String username, String domain) throws UsernameNotFoundException {if (StringUtils.isAnyBlank(username, domain)) {throw new UsernameNotFoundException("Username and domain must be provided");}User user = userRepository.findUser(username, domain);if (user == null) {throw new UsernameNotFoundException(String.format("Username not found for domain, username=%s, domain=%s", username, domain));}return user; }

4.3.自定義UserDetailsAuthenticationProvider

我們的CustomUserDetailsAuthenticationProvider將AbstractUserDetailsAuthenticationProvider和委托擴展到我們的CustomUserDetailService以檢索用戶。這個類最重要的特性是retrieveUser方法的實現。

請注意,我們必須將身份驗證令牌強制轉換為CustomAuthenticationToken才能訪問我們的自定義字段

@Override protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {CustomAuthenticationToken auth = (CustomAuthenticationToken) authentication;UserDetails loadedUser;try {loadedUser = this.userDetailsService.loadUserByUsernameAndDomain(auth.getPrincipal().toString(), auth.getDomain());} catch (UsernameNotFoundException notFound) {if (authentication.getCredentials() != null) {String presentedPassword = authentication.getCredentials().toString();passwordEncoder.matches(presentedPassword, userNotFoundEncodedPassword);}throw notFound;} catch (Exception repositoryProblem) {throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);}// ...return loadedUser; }

4.4.總結

我們的第二種方法幾乎與我們首先提出的簡單方法相同。通過實現我們自己的AuthenticationProvider和CustomAuthenticationToken,我們避免了需要使用自定義解析邏輯來調整我們的用戶名字段。

5.結論

在本文中,我們在Spring Security中實現了一個使用額外登錄字段的表單登錄。我們以兩種不同的方式做到了這一點

  • 在我們簡單的方法中,我們最小化了我們需要編寫的代碼量。通過使用自定義解析邏輯調整用戶名,我們能夠重用DaoAuthenticationProvider和UsernamePasswordAuthentication
  • 在我們更加個性化的方法中,我們通過擴展AbstractUserDetailsAuthenticationProvider并使用CustomAuthenticationToken提供我們自己的CustomUserDetailsService來提供自定義字段支持。
與往常一樣,所有源代碼都可以在GitHub上找到。

轉載于:https://www.cnblogs.com/xjknight/p/10919653.html

總結

以上是生活随笔為你收集整理的Spring Security在标准登录表单中添加一个额外的字段的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。