91精产品自偷自偷综合官网版下载-91精产品自偷自偷综合下-91精品-91精品91久久久-91精品成人-91精品成人www

網站建設資訊

NEWS

網站建設資訊

Spring3Security如何在標準登錄表單中添加一個額外的字段

這篇文章給大家分享的是有關Spring3 Security如何在標準登錄表單中添加一個額外的字段的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

目前成都創新互聯已為近1000家的企業提供了網站建設、域名、虛擬主機、網站托管、服務器托管、企業網站設計、二道江網站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協力一起成長,共同發展。

概述

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

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

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

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

2. Maven設置

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


 org.springframework.boot
 spring-boot-starter-parent
 2.0.0.M7
 

 

 
  org.springframework.boot
  spring-boot-starter-web
 
 
  org.springframework.boot
  spring-boot-starter-security
 
 
  org.springframework.boot
  spring-boot-starter-thymeleaf
  
  
  org.thymeleaf.extras
  thymeleaf-extras-springsecurity4
 

可以在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 SimpleAuthenticationFilter
 extends UsernamePasswordAuthenticationFilter {
 @Override
 public 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 {
 // ...
 @Override
 public 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提取的額外的字段:


 Please sign in
 

Example: user / domain / password

 Invalid user, password, or domain

 

 Username    

 

 Domain    

 

 Password    

 Sign in
 

Back to home page

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

image

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";
 @Override
 public 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上找到。

感謝各位的閱讀!關于“Spring3 Security如何在標準登錄表單中添加一個額外的字段”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!


分享名稱:Spring3Security如何在標準登錄表單中添加一個額外的字段
當前網址:http://www.yuzhuanjia.cn/article/geegjs.html
主站蜘蛛池模板: av永久高清中文字幕无码人妻一区二区 | 2025亚洲最新视频 | av无码在线之家国产亚洲精品久久久久久打不开 | 国产av巨作饥渴性店长 | 91精品国产综合久久婷婷香蕉 | 丰满人妻系列 | 波多野结衣车内乳精在线播放 | 国产av无码秘在线 | 波多野结高清无码中文观看下载 | av网站的免费观看 | 91中文字| 一区欧美人与动物 | 日韩av中文字幕免费在线观看 | 2025国产在线视频 | av潮喷大喷水系列无码 | 91久久国产亚洲精品 | 国产av一级毛片一区 | 午夜国产小视频 | 福利一区二区三区视频在线 | av免费网站在线观看 | av天堂亚洲mm | 91精品国产色 | 国产av无码专区亚洲av高潮 | 国产aⅴ日韩毛片 | 果冻传媒剧国产剧 | 91丝袜高潮流白浆潮喷在线观看 | 波多野结衣免费免费视频一区 | 国产白丝精品爽爽久久久久久蜜臀 | 91精品国产丝袜 | AV久久无码AV喷水高潮 | 99re6在线精品视频免费播放 | hd无码入口18综合二区暖暖 | 91精品人人妻人人澡人人爽人人精东影业 | 3dmax插入挤出 | 高潮毛片无遮挡高清免费软件 | 99久久免费精品国产72精品九九 | 福利一区在线视频 | AV无码偷拍在线观看 | 国产av一区二区三区懂色 | 波多野结衣家庭教师免费观看 | 91网站网站网站在线 |