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

Spring Security在標(biāo)準登錄表單中添加一個額外的字段

 更新時間:2019年05月26日 14:11:09   作者:程序猿Knight  
這篇文章主要介紹了Spring Security在標(biāo)準登錄表單中添加一個額外的字段,我們將重點關(guān)注兩種不同的方法,以展示框架的多功能性以及我們可以使用它的靈活方式。 需要的朋友可以參考下

概述

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

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

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

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

2. Maven設(shè)置

我們將使用Spring Boot啟動程序來引導(dǎo)我們的項目并引入所有必需的依賴項。
 我們將使用的設(shè)置需要父聲明,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.簡單的項目設(shè)置

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

關(guān)鍵組件包括:

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

3.1. 簡單Authentication Filter

在我們的SimpleAuthenticationFilter中,域和用戶名字段是從請求中提取的。我們連接這些值并使用它們來創(chuàng)建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服務(wù)

UserDetailsService定義了一個名為loadUserByUsername的方法。我們的實現(xiàn)提取用戶名和域名。然后將值傳遞給我們的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配置

我們的設(shè)置與標(biāo)準的Spring Security配置不同,因為我們在默認情況下通過調(diào)用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配置它?;叵胍幌拢覀兊腟impleUserDetailsService知道如何解析我們的用戶名和域字段,并返回在驗證時使用的相應(yīng)用戶。

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" rel="external nofollow" th:href="@{/index}" rel="external nofollow" >Back to home page</a></p>
</form>

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

image

3.5.總結(jié)

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

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

4.自定義項目設(shè)置

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

我們的第二種方法的關(guān)鍵組成部分包括:

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

4.1.自定義驗證過濾器

在我們的CustomAuthenticationFilter中,我們從請求中提取用戶名,密碼和域字段。這些值用于創(chuàng)建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服務(wù)

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

我們創(chuàng)建的CustomUserDetailsServiceImpl類只是實現(xiàn)并委托我們的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方法的實現(xiàn)。

請注意,我們必須將身份驗證令牌強制轉(zhuǎn)換為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.總結(jié)

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

5.結(jié)論

在本文中,我們在Spring Security中實現(xiàn)了一個使用額外登錄字段的表單登錄。我們以兩種不同的方式做到了這一點
•在我們簡單的方法中,我們最小化了我們需要編寫的代碼量。通過使用自定義解析邏輯調(diào)整用戶名,我們能夠重用DaoAuthenticationProvider和UsernamePasswordAuthentication
•在我們更加個性化的方法中,我們通過擴展AbstractUserDetailsAuthenticationProvider并使用CustomAuthenticationToken提供我們自己的CustomUserDetailsService來提供自定義字段支持。

與往常一樣,所有源代碼都可以在GitHub上找到。

總結(jié)

以上所述是小編給大家介紹的Spring Security在標(biāo)準登錄表單中添加一個額外的字段,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 基于Springboot+Mybatis對數(shù)據(jù)訪問層進行單元測試的方式分享

    基于Springboot+Mybatis對數(shù)據(jù)訪問層進行單元測試的方式分享

    本文將介紹一種快高效、可復(fù)用的解決測試方案——對數(shù)據(jù)訪問層做單元測試,文章通過代碼示例介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下
    2023-07-07
  • SpringBoot集成Mybatis+xml格式的sql配置文件操作

    SpringBoot集成Mybatis+xml格式的sql配置文件操作

    這篇文章主要介紹了SpringBoot集成Mybatis+xml格式的sql配置文件操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring6當(dāng)中獲取Bean的四種方式小結(jié)

    Spring6當(dāng)中獲取Bean的四種方式小結(jié)

    Spring 為Bean 的獲取提供了多種方式,通常包括4種方式,(也就是說在Spring中為Bean對象的創(chuàng)建準備了多種方案,目的是:更加靈活),本文將通過代碼示例詳細的給大家介紹了一下這四種方式,需要的朋友可以參考下
    2024-04-04
  • Java枚舉使用方法詳解

    Java枚舉使用方法詳解

    這篇文章主要為大家詳細介紹了Java枚舉的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • java中mybatis和hibernate的用法總結(jié)

    java中mybatis和hibernate的用法總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于java中mybatis和hibernate的用法總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-01-01
  • 深入解析Session工作原理及運行流程

    深入解析Session工作原理及運行流程

    這篇文章主要介紹了深入解析Session工作原理及運行流程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • JVM系列之:再談java中的safepoint說明

    JVM系列之:再談java中的safepoint說明

    這篇文章主要介紹了JVM系列之:再談java中的safepoint說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • mybatis空值插入處理的解決方法

    mybatis空值插入處理的解決方法

    本文主要介紹了mybatis空值插入處理的解決方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • MyBatis實現(xiàn)配置加載的步驟

    MyBatis實現(xiàn)配置加載的步驟

    本文主要介紹了MyBatis實現(xiàn)配置加載的步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • 詳解Spring Boot Security工作流程

    詳解Spring Boot Security工作流程

    Spring Security,這是一種基于 Spring AOP 和 Servlet 。這篇文章主要介紹了Spring Boot Security的相關(guān)知識,需要的朋友可以參考下
    2019-04-04

最新評論

永吉县| 洛扎县| 武陟县| 桑日县| 中超| 乐东| 张掖市| 阿拉善左旗| 五河县| 隆回县| 乌海市| 芜湖县| 泗洪县| 遂溪县| 巴彦淖尔市| 汤原县| 云安县| 周宁县| 万载县| 德庆县| 余干县| 安阳市| 赤峰市| 开平市| 海南省| 苏尼特左旗| 甘谷县| 晋宁县| 应用必备| 东阿县| 汝阳县| 平安县| 庆安县| 秀山| 江川县| 东明县| 远安县| 漳浦县| 汝城县| 隆林| 万荣县|