spring security的基本原理、配置使用方式
一、Spring Security 基本原理
Spring Security 主要通過一系列過濾器鏈(Filter Chain)來實現安全控制。核心流程如下:
- 請求進入過濾器鏈(如
UsernamePasswordAuthenticationFilter、BasicAuthenticationFilter等)。 - 認證管理:通過
AuthenticationManager進行身份認證。 - 授權管理:通過
AccessDecisionManager判斷當前用戶是否有權限訪問資源。 - 異常處理:如認證失敗、權限不足等。
二、Spring Security 配置方式
1. 依賴引入
如果是 Spring Boot 項目,只需在 pom.xml 添加:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>2. 基本配置類(推薦方式:Java Config)
創(chuàng)建一個配置類,繼承 WebSecurityConfigurerAdapter(Spring Security 5.7+ 推薦實現 SecurityFilterChain Bean)。
方式一:使用WebSecurityConfigurerAdapter(舊版)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() // 配置授權規(guī)則
.antMatchers("/public/**").permitAll() // 允許所有人訪問
.antMatchers("/admin/**").hasRole("ADMIN") // 僅ADMIN角色可訪問
.anyRequest().authenticated() // 其他請求需認證
.and()
.formLogin() // 使用表單登錄
.loginPage("/login") // 自定義登錄頁
.permitAll()
.and()
.logout()
.permitAll();
}
}方式二:使用SecurityFilterChainBean(推薦)
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.antMatchers("/public/**").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin(form -> form
.loginPage("/login")
.permitAll()
)
.logout(logout -> logout.permitAll());
return http.build();
}
}3. 用戶認證配置
可以自定義用戶信息來源,比如內存、數據庫等。
內存用戶配置
@Bean
public InMemoryUserDetailsManager userDetailsService() {
UserDetails user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetails admin = User.withDefaultPasswordEncoder()
.username("admin")
.password("admin")
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}自定義UserDetailsService(如從數據庫讀取用戶)
@Service
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserEntity user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found");
}
return new User(user.getUsername(), user.getPassword(), getAuthorities(user));
}
private Collection<? extends GrantedAuthority> getAuthorities(UserEntity user) {
// 根據實際情況返回角色列表
return AuthorityUtils.createAuthorityList("ROLE_USER");
}
}4. 常見功能配置
1. 禁用 CSRF(開發(fā)調試時可用,生產建議開啟)
http.csrf().disable();
2. 配置靜態(tài)資源免認證
.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/images/**").permitAll()3. 配置自定義登錄成功/失敗處理
.formLogin()
.successHandler(mySuccessHandler)
.failureHandler(myFailureHandler)4. 配置 Remember-Me 功能
.rememberMe()
.tokenValiditySeconds(86400)
.key("mySecretKey")三、常見使用場景舉例
1. RESTful 接口安全(無狀態(tài))
http
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();2. 角色和權限控制
.authorizeRequests()
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.antMatchers("/admin/**").hasRole("ADMIN")3. 方法級安全
開啟注解支持:
@EnableGlobalMethodSecurity(prePostEnabled = true)
在 Service 層方法上使用:
@PreAuthorize("hasRole('ADMIN')")
public void adminMethod() { ... }四、常見問題
密碼存儲建議使用加密算法(如 BCrypt):
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}- 登錄接口自定義返回 JSON:需自定義
AuthenticationSuccessHandler和AuthenticationFailureHandler。 - 前后端分離項目建議關閉 CSRF,并使用 JWT 或 Token 認證。
五、官方文檔與參考
六、進階配置與應用
1. 自定義登錄邏輯(前后端分離常用)
對于前后端分離項目,通常不使用 Spring Security 默認的表單登錄,而是自定義登錄接口,并返回 JSON 響應。
步驟:
1. 禁用默認登錄頁面和 CSRF
http
.csrf().disable()
.formLogin().disable();2. 自定義登錄接口
在 Controller 層實現登錄接口,手動認證用戶:
@RestController
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
try {
Authentication authentication = authenticationManager.authenticate(authToken);
// 認證成功,生成 JWT 或返回用戶信息
return ResponseEntity.ok(/* token or user info */);
} catch (AuthenticationException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("登錄失敗");
}
}
}3. 配置 AuthenticationManager Bean
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}2. JWT(Json Web Token)整合
JWT 適用于前后端分離和 RESTful API 項目,實現無狀態(tài)認證。
1. 依賴引入
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>2. JWT 工具類
public class JwtUtil {
private static final String SECRET_KEY = "yourSecretKey";
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 86400000))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static String getUsernameFromToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}3. JWT 過濾器
在 Spring Security 過濾器鏈中添加 JWT 校驗:
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
String jwt = token.replace("Bearer ", "");
String username = JwtUtil.getUsernameFromToken(jwt);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
chain.doFilter(request, response);
}
}4. 注冊過濾器
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
3. 異常處理(認證失敗/權限不足)
1. 未認證異常處理
http.exceptionHandling()
.authenticationEntryPoint((request, response, authException) -> {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("{\"error\":\"未認證\"}");
});2. 權限不足異常處理
.accessDeniedHandler((request, response, accessDeniedException) -> {
response.setContentType("application/json;charset=UTF-8");
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write("{\"error\":\"權限不足\"}");
});4. 常見安全防護措施
1. 防止密碼明文存儲
始終使用加密算法存儲密碼,比如 BCrypt:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}2. 防止 XSS/CSRF 攻擊
- 默認開啟 CSRF,前后端分離項目建議關閉并采用 Token 防護。
- 對輸入內容進行過濾和轉義。
3. 防止 Session Fixation(會話固定攻擊)
http.sessionManagement()
.sessionFixation().migrateSession();4. 限制登錄嘗試次數(防暴力破解)
可結合 Redis、數據庫等記錄登錄失敗次數,超過閾值后鎖定賬號。
5. 方法級安全進階
@Secured("ROLE_ADMIN")@PreAuthorize("hasAuthority('sys:user:view')")@PostAuthorize("returnObject.username == authentication.name")
使用方式:
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
七、Spring Security 與 OAuth2、SSO 等整合
Spring Security 支持與 OAuth2、OpenID Connect、CAS 等單點登錄系統(tǒng)整合,具體可參考 Spring Security OAuth2 文檔。
- Spring Security OAuth2 Client:實現第三方登錄(如微信、支付寶、GitHub)。
- Spring Authorization Server:自建 OAuth2 授權服務。
八、調試與排錯建議
- 查看過濾器鏈
- 可在啟動日志中查找
FilterChainProxy,或通過斷點調試。
- 可在啟動日志中查找
- 認證流程排查
- 重點關注
UserDetailsService、AuthenticationManager、PasswordEncoder配置是否正確。
- 重點關注
- 權限控制問題
檢查角色前綴(ROLE_)、方法注解是否生效。
總結
Spring Security 配置靈活、功能強大,推薦使用 Java 配置方式(即 SecurityFilterChain Bean),并根據實際需求自定義用戶認證、授權、異常處理等。對于前后端分離、RESTful API 項目,建議使用無狀態(tài)認證(如 JWT),并合理配置安全策略。
到此這篇關于spring security 配置使用的文章就介紹到這了,更多相關spring security 配置使用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot實現將自定義日志格式存儲到mongodb中
這篇文章主要介紹了springboot實現將自定義日志格式存儲到mongodb中的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
SpringBoot3.x整合Swagger的過程及注意事項
Swagger是一個用于生成、描述、調用和可視化Restful風格的web服務的規(guī)范和完整框架,接下來通過本文給大家介紹2025-11-11
Java基礎之Comparable與Comparator概述
這篇文章主要介紹了Java基礎之Comparable與Comparator詳解,文中有非常詳細的代碼示例,對正在學習java基礎的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04
springboot程序啟動慢-未配置hostname的解決
這篇文章主要介紹了springboot程序啟動慢-未配置hostname的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08

