欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot實現(xiàn)單點登錄的實現(xiàn)詳解

 更新時間:2023年05月31日 10:58:46   作者:FeereBug  
在現(xiàn)代的Web應(yīng)用程序中,單點登錄(Single?Sign-On)已經(jīng)變得越來越流行,在本文中,我們將使用Spring?Boot構(gòu)建一個基本的單點登錄系統(tǒng),需要的可以參考一下

前言

在現(xiàn)代的Web應(yīng)用程序中,單點登錄(Single Sign-On)已經(jīng)變得越來越流行。單點登錄使得用戶只需要一次認(rèn)證即可訪問多個應(yīng)用程序,同時也提高了應(yīng)用程序的安全性。Spring Boot作為一種廣泛使用的Web開發(fā)框架,在單點登錄方面也提供了很好的支持。

在本文中,我們將使用Spring Boot構(gòu)建一個基本的單點登錄系統(tǒng)。我們將介紹如何使用Spring Security和JSON Web Tokens(JWTs)來實現(xiàn)單點登錄功能。本文假設(shè)您已經(jīng)熟悉Spring Boot和Spring Security。

什么是JWT

在介紹實現(xiàn)單點登錄之前,讓我們先了解一下JWT。JWT是一種基于JSON格式的開放標(biāo)準(zhǔn)(RFC 7519),用于在不同的應(yīng)用程序之間安全地傳輸信息。它由三個部分組成:

  • 標(biāo)頭(Header):包含JWT的類型和使用的簽名算法。
  • 負(fù)載(Payload):包含實際的信息。
  • 簽名(Signature):使用私鑰生成的簽名,用于驗證JWT的真實性。

JWT通常在身份驗證過程中使用,以便在不需要存儲用戶信息的情況下驗證用戶身份。由于JWT是基于標(biāo)準(zhǔn)化的JSON格式構(gòu)建的,因此在多種編程語言中都可以輕松地實現(xiàn)和解析。

實現(xiàn)單點登錄

下面我們來介紹如何使用JWT實現(xiàn)基本的單點登錄系統(tǒng)。這個系統(tǒng)由兩個應(yīng)用程序組成:認(rèn)證應(yīng)用程序和資源應(yīng)用程序。用戶在認(rèn)證應(yīng)用程序上進行一次身份驗證之后,就可以訪問資源應(yīng)用程序。

認(rèn)證應(yīng)用程序

我們首先需要構(gòu)建一個認(rèn)證應(yīng)用程序,用于認(rèn)證用戶信息并生成JWT。

添加依賴

首先,我們需要添加以下依賴:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • spring-boot-starter-security:用于提供基本的安全性支持。
  • jjwt:JSON Web Token的Java實現(xiàn)。
  • spring-boot-starter-web:用于提供Web應(yīng)用程序支持。

配置Spring Security

接下來,我們需要配置Spring Security。我們將使用Spring Security的默認(rèn)配置,并添加一個自定義的UserDetailsService來從數(shù)據(jù)庫中加載用戶信息。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  private UserDetailsService userDetailsService;
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .authorizeRequests()
        .antMatchers("/auth/**").permitAll()
        .anyRequest().authenticated()
      .and().formLogin()
        .loginPage("/auth/login")
        .successHandler(authenticationSuccessHandler())
        .failureHandler(authenticationFailureHandler())
        .permitAll()
      .and().logout()
        .logoutUrl("/auth/logout")
        .logoutSuccessUrl("/auth/login?logout")
        .invalidateHttpSession(true)
        .deleteCookies("JSESSIONID");
  }
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
  }
  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }
  @Bean
  public AuthenticationSuccessHandler authenticationSuccessHandler() {
    return new JWTAuthenticationSuccessHandler();
  }
  @Bean
  public AuthenticationFailureHandler authenticationFailureHandler() {
    return new JWTAuthenticationFailureHandler();
  }
}

在上述配置中,我們定義了一個路由表達(dá)式"/auth/**"允許匿名訪問,這意味著認(rèn)證應(yīng)用程序的登錄和注冊頁面可以被未經(jīng)身份驗證的用戶訪問。我們還定義了自定義的AuthenticationSuccessHandler和AuthenticationFailureHandler,用于在用戶身份驗證成功或失敗時生成JWT并將其返回給用戶。這些處理程序?qū)⒃谙乱徊街袑崿F(xiàn)。

實現(xiàn)自定義的AuthenticationSuccessHandler和AuthenticationFailureHandler

在上述配置中,我們使用了自定義的AuthenticationSuccessHandler和AuthenticationFailureHandler。讓我們來實現(xiàn)它們。

public class JWTAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
  private static final String JWT_SECRET = "secret";
  private static final long JWT_EXPIRATION_TIME = 864000000; // 10 days
  @Override
  public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
    Authentication authentication) throws IOException, ServletException {
    String username = authentication.getName();
    String token = Jwts.builder()
      .setSubject(username)
      .setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION_TIME))
      .signWith(SignatureAlgorithm.HS512, JWT_SECRET.getBytes())
      .compact();
    response.setHeader("Authorization", "Bearer " + token);
    response.getWriter().write("{\"token\":\"Bearer " + token + "\"}");
    response.setContentType("application/json");
  }
}

在上述代碼中,我們使用了JJWT庫來生成JWT。在onAuthenticationSuccess方法中,我們首先從Authentication對象獲取用戶名,然后使用用戶名創(chuàng)建JWT。我們設(shè)置JWT的有效期為10天,并使用HS512簽名算法對JWT進行簽名,使用一個字符串作為密鑰。最后,我們將JWT作為Bearer令牌添加到響應(yīng)消息頭中,并封裝在JSON格式的響應(yīng)體中返回給客戶端。

public class JWTAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
  @Override
  public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
    AuthenticationException exception) throws IOException, ServletException {
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    response.getWriter().write("{\"error\":\"Bad credentials\"}");
    response.setContentType("application/json");
  }
}

在上述代碼中,我們將響應(yīng)代碼設(shè)置為401(未經(jīng)授權(quán)),并向響應(yīng)體中添加一個錯誤消息,以通知客戶端身份驗證失敗。

實現(xiàn)授權(quán)控制器

現(xiàn)在我們已經(jīng)創(chuàng)建了認(rèn)證應(yīng)用程序的基本安全性,讓我們來構(gòu)建資源應(yīng)用程序并實現(xiàn)授權(quán)控制器,以確保只有經(jīng)過身份驗證的用戶才可以訪問受保護的資源。我們將使用JWT來驗證用戶身份。

@RestController
public class ResourceController {
  private static final String JWT_SECRET = "secret";
  @GetMapping("/resource")
  public ResponseEntity<String> getResource(HttpServletRequest request) {
    String token = request.getHeader("Authorization").replace("Bearer ", "");
    if (isValidJWT(token)) {
      return ResponseEntity.ok("Protected resource");
    } else {
      return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
    }
  }
  private boolean isValidJWT(String jwt) {
    try {
      Jwts.parser().setSigningKey(JWT_SECRET.getBytes()).parseClaimsJws(jwt);
      return true;
    } catch (JwtException e) {
      return false;
    }
  }
}

在上述代碼中,我們使用了一個示例的受保護資源路徑"/resource",該路徑只允許經(jīng)過身份驗證的用戶訪問。我們從請求頭中提取Bearer令牌,并使用isValidJWT方法驗證令牌的真實性。如果JWT有效,則返回200響應(yīng)代碼和受保護的資源;否則返回401(未經(jīng)授權(quán))響應(yīng)代碼。

資源應(yīng)用程序

現(xiàn)在我們已經(jīng)創(chuàng)建了認(rèn)證應(yīng)用程序,讓我們來創(chuàng)建一個資源應(yīng)用程序,以便用戶可以在驗證后訪問它。資源應(yīng)用程序?qū)Ⅱ炞C用戶是否具有訪問受保護資源的權(quán)限。

配置Spring Security

我們首先需要配置Spring Security,以使資源應(yīng)用程序能夠驗證JWT并授予用戶訪問權(quán)限。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .authorizeRequests()
      .antMatchers("/resource").authenticated()
      .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and().addFilterBefore(new JWTAuthorizationFilter(), UsernamePasswordAuthenticationFilter.class);
  }
}

在上述配置中,我們定義了一個路由表達(dá)式"/resource",只有經(jīng)過身份驗證的用戶才能訪問。我們還將會話管理策略設(shè)置為STATELESS,以避免使用HTTP會話。

實現(xiàn)JWTAuthorizationFilter

接下來,我們需要實現(xiàn)JWTAuthorizationFilter,以驗證來自客戶端的JWT并將其與用戶信息相關(guān)聯(lián)。這將允許我們檢查用戶是否具有訪問資源的權(quán)限。

public class JWTAuthorizationFilter extends OncePerRequestFilter {
  private static final String JWT_SECRET = "secret";
  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
    FilterChain filterChain) throws ServletException, IOException {
    String authorizationHeader = request.getHeader("Authorization");
    if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
      filterChain.doFilter(request, response);
      return;
    }
    String jwt = authorizationHeader.replace("Bearer ", "");
    try {
      Jws<Claims> claimsJws = Jwts.parser().setSigningKey(JWT_SECRET.getBytes()).parseClaimsJws(jwt);
      String username = claimsJws.getBody().getSubject();
      List<GrantedAuthority> authorities = new ArrayList<>();
      UserDetails userDetails = new User(username, "", authorities);
      UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
        userDetails, null, userDetails.getAuthorities());
      SecurityContextHolder.getContext().setAuthentication(authentication);
    } catch (JwtException e) {
      throw new ServletException("Invalid JWT");
    }
    filterChain.doFilter(request, response);
  }
}

在上述代碼中,我們查詢Authorization頭以查找Bearer令牌。如果令牌不存在或不正確,則請求將繼續(xù)傳遞。否則,我們使用JJWT庫驗證JWT的真實性,并獲取用戶的用戶名。我們將用戶名創(chuàng)建為Spring Security的UserDetails對象并創(chuàng)建一個UsernamePasswordAuthenticationToken,用于將身份驗證信息設(shè)置為當(dāng)前Spring Security上下文的一部分。完成后,請求將繼續(xù)傳遞并授權(quán)用戶訪問資源。

測試

現(xiàn)在我們已經(jīng)創(chuàng)建了認(rèn)證應(yīng)用程序和資源應(yīng)用程序,讓我們對它們進行測試。首先,我們在認(rèn)證應(yīng)用程序上注冊并登錄,以獲取JWT令牌。然后,我們將使用該令牌訪問資源應(yīng)用程序的受保護資源,并驗證我們是否可以成功訪問。

# Register and login to authentication application
$ curl -s -X POST -H "Content-Type: application/json" -d '{"username":"user","password":"password"}' http://localhost:8080/auth/signup
$ curl -s -X POST -H "Content-Type: application/json" -d '{"username":"user","password":"password"}' http://localhost:8080/auth/login

# Get JWT token
$ TOKEN=$(curl -si -X POST -H "Content-Type: application/json" -d '{"username":"user","password":"password"}' http://localhost:8080/auth/login | grep 'Authorization:' | awk '{print $2}')

# Access protected resource in resource application
$ curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8090/resource
Protected resource

通過測試,我們可以看到我們成功地訪問了資源應(yīng)用程序的受保護資源,并返回了正確的響應(yīng)。

總結(jié)

在本文中,我們使用Spring Boot,Spring Security和JWT實現(xiàn)了一個基本的單點登錄系統(tǒng)。我們介紹了JWT的概念,并演示了如何使用它來驗證用戶身份。我們還創(chuàng)建了一個認(rèn)證應(yīng)用程序和一個資源應(yīng)用程序,以演示如何在多個應(yīng)用程序之間共享用戶身份驗證信息。您可以將此范例用作基礎(chǔ)模板,進一步擴展它以適應(yīng)自己的應(yīng)用程序需求。

以上就是SpringBoot實現(xiàn)單點登錄的實現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot單點登錄的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MyBatis-Plus忽略多租戶隔離自定義注解

    MyBatis-Plus忽略多租戶隔離自定義注解

    本文主要介紹了MyBatis-Plus忽略多租戶隔離自定義注解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-12-12
  • Fastjson反序列化隨機性失敗示例詳解

    Fastjson反序列化隨機性失敗示例詳解

    這篇文章主要為大家介紹了Fastjson反序列化隨機性失敗示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-08-08
  • Java常用工具類匯總 附示例代碼

    Java常用工具類匯總 附示例代碼

    這篇文章主要介紹了Java常用工具類匯總 附示例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Java中Boolean引發(fā)缺陷的解決

    Java中Boolean引發(fā)缺陷的解決

    本文主要介紹了Java中Boolean引發(fā)缺陷的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • springboot使用注解實現(xiàn)鑒權(quán)功能

    springboot使用注解實現(xiàn)鑒權(quán)功能

    這篇文章主要介紹了springboot使用注解實現(xiàn)鑒權(quán)功能,本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • SpringBoot整合flyway實現(xiàn)步驟解析

    SpringBoot整合flyway實現(xiàn)步驟解析

    這篇文章主要介紹了SpringBoot整合flyway實現(xiàn)步驟解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • 如何徹底刪除SVN中的文件和文件夾(附恢復(fù)方法)

    如何徹底刪除SVN中的文件和文件夾(附恢復(fù)方法)

    在SVN中如果刪除某個文件或文件夾也可以在歷史記錄中進行找回,有的時候需要徹底刪除某些文件,即不希望通過歷史記錄進行恢復(fù),需要在服務(wù)器上對SVN的數(shù)據(jù)進行重新整理
    2014-08-08
  • MyBatis實現(xiàn)批量插入數(shù)據(jù),多重forEach循環(huán)

    MyBatis實現(xiàn)批量插入數(shù)據(jù),多重forEach循環(huán)

    這篇文章主要介紹了MyBatis實現(xiàn)批量插入數(shù)據(jù),多重forEach循環(huán)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java實用工具庫commons-lang3的使用

    Java實用工具庫commons-lang3的使用

    Apache?Commons?Lang?3是一個流行的Java實用工具庫,提供了對java.lang包的擴展,包括字符串操作、正則表達(dá)式處理、數(shù)字操作、日期和時間操作、隨機字符串生成和對象操作等功能
    2025-03-03
  • java自定義攔截器用法實例

    java自定義攔截器用法實例

    這篇文章主要介紹了java自定義攔截器用法,實例分析了java自定義攔截器的實現(xiàn)與使用技巧,需要的朋友可以參考下
    2015-06-06

最新評論