一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

云服務器|WEB服務器|FTP服務器|郵件服務器|虛擬主機|服務器安全|DNS服務器|服務器知識|Nginx|IIS|Tomcat|

服務器之家 - 服務器技術 - 服務器知識 - 基于Spring Security的身份驗證與授權框架構建指南

基于Spring Security的身份驗證與授權框架構建指南

2024-01-04 06:47未知服務器之家 服務器知識

環境:SpringBoot2.7.12 1. 簡介 Spring Security是一個功能強大且高度可定制的身份驗證和訪問控制框架,用于保護基于Spring的應用程序。它采用AOP思想,基于servlet過濾器實現安全框架。 Spring Security具有以下優勢: 豐富的功能:Spring Se

環境:SpringBoot2.7.12

1. 簡介

Spring Security是一個功能強大且高度可定制的身份驗證和訪問控制框架,用于保護基于Spring的應用程序。它采用AOP思想,基于servlet過濾器實現安全框架。

Spring Security具有以下優勢:

  • 豐富的功能:Spring Security提供了完善的認證機制和方法級的授權功能,可以輕松地擴展以滿足自定義需求。
  • 強大的社區支持:與所有Spring項目一樣,Spring Security的真正強大之處在于可以輕松擴展以滿足自定義要求。此外,它擁有一個活躍的社區,提供了豐富的資源和支持。
  • 與Spring生態系統的集成:Spring Security與Spring生態系統中的其他組件緊密集成,如Spring MVC、Spring Boot等,使得在構建安全應用程序時更加便捷。
  • 高度可定制:Spring Security提供了大量的配置選項和擴展點,可以根據具體需求進行定制。

本篇文章將會介紹常用的配置及相應的擴展點。

2. 實戰案例

2.1 自定義配置

在Spring Security5.7之前版本通過繼承WebSecurityConfigurerAdapter類

public class SecurityConfig extends WebSecurityConfigurerAdapter {
}

5.7之后版本

@Bean
public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
  // ...
}

在這里每定義一個SecurityFilterChain所注入的HttpSecurity都是唯一的實例對象。

后續所有的配置都是基于Spring Security5.7.8版本

2.2 自定義驗證器

@Component
public class MemeryAuthticationProvider implements AuthenticationProvider {


  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication ;
    Object principal = token.getPrincipal() ;
    Object credentials = token.getCredentials() ;
    User user = users.get(principal) ;
    // notNull(user, "用戶名或密碼錯誤") ;
    if (user == null) {
      return null ;
    }
    
    if (!user.getPassword().equals(credentials)) {
      throw new RuntimeException("密碼錯誤") ;
    }
    return new UsernamePasswordAuthenticationToken(principal, credentials, user.getAuthorities()) ;
  }


  @Override
  public boolean supports(Class<?> authentication) {
    return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication) ;
  }


}

通過上面自定義認證器可以實現自己的驗證邏輯。

2.2 自定義UserDetailsService

通過自定義UserDetailsService也可以實現對應的邏輯,只不過這種方式你還需要提供一個PasswordEncoder

@Bean
public UserDetailsService userDetailsService() {
  return new UserDetailsService() {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      return users.get(username) ;
    }
  };
}


@Bean
public PasswordEncoder passwordEncoder() {
  return new PasswordEncoder() {
    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
      return rawPassword.equals(encodedPassword) ;
    }
    @Override
    public String encode(CharSequence rawPassword) {
      return rawPassword.toString() ;
    }
  };
}

2.3 攔截指定路徑的請求

@Bean
public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
  http.csrf().disable() ;
  // 該過濾器鏈,只匹配/api/**路徑的請求
    http.requestMatcher(new AntPathRequestMatcher("/api/**")) ;
    // 也可以這樣配置多個
    // http.requestMatchers().antMatchers("/api/**", "/admin/**") ;
  // ...
  DefaultSecurityFilterChain chain = http.build();
  return chain ;
}

2.4 攔截指定路徑及權限

@Bean
public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
  http.csrf().disable() ;
  http.authorizeHttpRequests().requestMatchers(new AntPathRequestMatcher("/api/save")).hasAnyRole("C") ;
  http.authorizeHttpRequests().requestMatchers(new AntPathRequestMatcher("/api/find")).hasAuthority("ROLE_U") ;
  DefaultSecurityFilterChain chain = http.build();
  return chain ;
}

2.5 自定義授權決定

http.authorizeHttpRequests(registry -> {
  registry.antMatchers("/api/{id}").access(new AuthorizationManager<RequestAuthorizationContext>() {
    @Override
    public AuthorizationDecision check(Supplier<Authentication> authentication,
        RequestAuthorizationContext object) {
      Map<String, String> variables = object.getVariables() ;
      // 返回的路徑是/api/666則進行攔截并且指定具有'D'的權限
      return new AuthorityAuthorizationDecision(variables.get("id").equals("666"), Arrays.asList(new SimpleGrantedAuthority("D"))) ;
    }
  }) ;
}) ;

2.6 自定義異常處理

http.exceptionHandling(customizer -> {
  customizer.accessDeniedHandler(new AccessDeniedHandler() {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
        AccessDeniedException accessDeniedException) throws IOException, ServletException {
      Map<String, Object> errors = new HashMap<>() ;
      response.setContentType("application/json;charset=utf-8") ;
      errors.put("code", -1) ;
      errors.put("status", response.getStatus()) ;
      errors.put("message", accessDeniedException.getMessage()) ;
      errors.put("details", ExceptionUtils.getMessage(accessDeniedException)) ;
      response.getWriter().println(new ObjectMapper().writeValueAsString(errors)) ;
    }
  }) ;
}) ;

2.7 自定義角色繼承

@Bean
public RoleHierarchy hierarchyVoter() {
  RoleHierarchyImpl hierarchy = new RoleHierarchyImpl();
  // ADMIN自動擁有MANAGER的權限
  hierarchy.setHierarchy("ROLE_ADMIN > ROLE_MANAGER");
  return hierarchy ;
}

2.8 自定義退出登錄邏輯

http.logout().logoutUrl("/logout").addLogoutHandler(new LogoutHandler() {
  @Override
  public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
    System.out.println("退出登錄") ;
  }
}).logoutSuccessHandler(new LogoutSuccessHandler() {
  @Override
  public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
      throws IOException, ServletException {
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter() ;
    out.println("<h2>退出登錄成功</h2>") ;
    out.close() ; 
  }
}) ;

2.9 自定義登錄失敗邏輯

http
  .formLogin()
  .failureHandler(new AuthenticationFailureHandler() {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception
      response.setContentType("application/json;charset=UTF-8") ;
      PrintWriter out = response.getWriter() ;
      out.println("{\"code\": -1, \"message\": \"" + getRootCause(exception).getMessage() + "\"}") ;
      out.close();
    }
  });

2.10 自定義過濾器

@Bean
public PackAuthenticationFilter packAuthenticationFilter() {
  return new PackAuthenticationFilter() ;
}
// 添加自定義過濾器到Security Filter Chain中
http.addFilterBefore(packAuthenticationFilter(), RequestCacheAwareFilter.class) ;

2.11 配置多個過濾器鏈

@Bean
public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
  // 攔截/api/**
  http.requestMatcher(new AntPathRequestMatcher("/api/**")) ;
}
@Bean
public SecurityFilterChain apiSecurityFilterChain(HttpSecurity http) throws Exception {
  // 攔截/admin/**
  http.requestMatcher(new AntPathRequestMatcher("/admin/**")) ;
}

2.12 開啟全局方法攔截

@Configuration
@EnableGlobalMethodSecurity(jsr250Enabled = true, prePostEnabled = true, securedEnabled = true)
public class SecurityConfig {}
// 使用
@GetMapping("/find")
@PreAuthorize("hasRole('GUEST')")
public Object find(HttpServletResponse response) throws Exception {
  return "find method invoke..." ;
}

2.13 國際化支持

@Bean
public ReloadableResourceBundleMessageSource messageSource() {
  ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
  // 這里會按照順序查找的
  messageSource.addBasenames(
      "classpath:org/springframework/security/messages",
      "classpath:messages/messages"
  ) ;
  return messageSource ;
}

2.14 防止重復登錄

http.sessionManagement().maximumSessions(1).expiredSessionStrategy(new SessionInformationExpiredStrategy() {
  @Override
  public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
    HttpServletResponse response = event.getResponse() ;
    response.setContentType("application/json;charset=UTF-8");
    PrintWriter out = response.getWriter();
    out.println("{\"code\": -1, \"message\": \"會話已過期,或重復登錄\"}");
    out.close();
  }
}) ;

注意:你的UserDetails必須重寫equals和hashCode方法

總結:以上是在實際開發中經常會應用到的一些配置及相應功能的使用。Spring Security是一個強大的安全認證框架,它提供了豐富的安全功能來保護您的應用程序。通過本文的基礎配置示例,你可以輕松地開始使用Spring Security來保護你的應用程序并實現身份驗證和授權功能。

完畢!!!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩性公交车上xxhd免费 | 99久久精品久久久久久清纯 | 性色香蕉AV久久久天天网 | 亚洲2卡三卡4卡5卡精品 | 2019午夜福合集高清完整版 | 亚洲福利一区二区 | 极品久久| 韩国黄色网址 | 国产自产自拍 | 99日影院在线播放 | 四虎永久在线精品免费影视 | 国产香蕉97碰碰久久人人 | 91素人约啪 | 国产区成人综合色在线 | 久久机热视频 这里只有精品首页 | 边吃胸边膜下刺激免费男对女 | 亚洲国产99999在线精品一区 | 国产成人v爽在线免播放观看 | 日本在线国产 | 亚洲国产精品嫩草影院永久 | 99热6这里只有精品 99欧美精品 | 18性夜影院午夜寂寞影院免费 | 91精品久久一区二区三区 | 91午夜视频 | 欧美又大又粗又长又硬 | 亚洲国产欧美在线成人aaaa | 黄色大片网站 | 国产成人高清精品免费观看 | 国产清纯女高中生在线观看 | 黑人巨大vs北条麻妃在线 | 深夜在线影院 | 9420高清完整版在线观看国语 | 国产精品99在线观看 | 精品一久久香蕉国产线看观 | 五月天精品视频在线观看 | 操美女骚b| 国产午夜精品一区二区 | 好吊色青青青国产综合在线观看 | 亚洲精品国精品久久99热 | 九九99九九精彩网站 | 天天草天天 |