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

Java中Spring Security的使用及最佳實踐

 更新時間:2025年07月28日 16:22:36   作者:冉成未來  
Spring Security是Spring生態(tài)中的安全框架,提供認(rèn)證、授權(quán)、攻擊防護(hù)及OAuth2/JWT集成等核心功能,支持靈活配置如內(nèi)存/數(shù)據(jù)庫認(rèn)證與密碼加密,適用于構(gòu)建安全應(yīng)用,本文給大家介紹Java中Spring Security的使用及最佳實踐,感興趣的朋友一起看看吧

1. Spring Security 簡介

Spring Security 是一個功能強(qiáng)大且高度可定制的身份驗證和訪問控制框架,它是 Spring 生態(tài)系統(tǒng)中的標(biāo)準(zhǔn)安全框架。主要提供以下功能:

  • 認(rèn)證(Authentication):驗證用戶身份
  • 授權(quán)(Authorization):控制用戶訪問權(quán)限
  • 防護(hù)攻擊:防止 CSRF、會話固定等攻擊
  • 與其他技術(shù)集成:如 OAuth2、LDAP 等

2. 快速開始

2.1 添加依賴

對于 Maven 項目,在 pom.xml 中添加:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

對于 Gradle 項目:

implementation 'org.springframework.boot:spring-boot-starter-security'

2.2 基本配置

創(chuàng)建一個配置類繼承 WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
    @Bean
    @Override
    public UserDetailsService userDetailsService() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("user")
            .password("password")
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

3. 詳細(xì)配置

3.1 認(rèn)證配置

內(nèi)存認(rèn)證

WebSecurityConfigurerAdapter.java

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .inMemoryAuthentication()
            .withUser("user").password("{noop}password").roles("USER")
            .and()
            .withUser("admin").password("{noop}admin").roles("ADMIN");
}

JDBC 認(rèn)證(可選)

WebSecurityConfigurerAdapter.java

@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
        .jdbcAuthentication()
            .dataSource(dataSource)
            .usersByUsernameQuery("select username,password,enabled from users where username=?")
            .authoritiesByUsernameQuery("select username,authority from authorities where username=?");
}

自定義 UserDetailsService

@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
            .orElseThrow(() -> new UsernameNotFoundException("User not found"));
        return new org.springframework.security.core.userdetails.User(
            user.getUsername(), 
            user.getPassword(), 
            getAuthorities(user.getRoles()));
    }
    private Collection<? extends GrantedAuthority> getAuthorities(Collection<Role> roles) {
        return roles.stream()
            .map(role -> new SimpleGrantedAuthority(role.getName()))
            .collect(Collectors.toList());
    }
}

3.2 授權(quán)配置

WebSecurityConfigurerAdapter.java

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
            .antMatchers("/public/**").permitAll()
            .anyRequest().authenticated()
        .and()
        .formLogin()
            .loginPage("/login")
            .defaultSuccessUrl("/dashboard")
            .failureUrl("/login?error=true")
            .permitAll()
        .and()
        .logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/login?logout=true")
            .invalidateHttpSession(true)
            .deleteCookies("JSESSIONID")
            .permitAll()
        .and()
        .rememberMe()
            .key("uniqueAndSecret")
            .tokenValiditySeconds(86400);
}

3.3 密碼加密

推薦使用 BCrypt 密碼編碼器:
WebSecurityConfigurerAdapter.java

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

然后在用戶注冊時加密密碼:
WebSecurityConfigurerAdapter.java

@Autowired
private PasswordEncoder passwordEncoder;
public void registerUser(User user) {
    user.setPassword(passwordEncoder.encode(user.getPassword()));
    userRepository.save(user);
}

4. 高級特性

4.1 CSRF 防護(hù)

Spring Security 默認(rèn)啟用 CSRF 防護(hù)。在表單中添加 CSRF 令牌:

<form method="post">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    <!-- 其他表單字段 -->
</form>

或者在 AJAX 請求中添加:

var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
    xhr.setRequestHeader(header, token);
});

4.2 方法級安全

啟用方法級安全:

@Configuration
@EnableGlobalMethodSecurity(
    prePostEnabled = true,
    securedEnabled = true,
    jsr250Enabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
}

然后在方法上使用注解:

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long userId) {
    // ...
}
@PostAuthorize("returnObject.owner == authentication.name")
public Document getDocument(Long docId) {
    // ...
}
@Secured("ROLE_ADMIN")
public void updateUser(User user) {
    // ...
}

4.3 OAuth2 集成

添加依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

配置 OAuth2 客戶端:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: your-client-id
            client-secret: your-client-secret
            scope: email, profile

4.4 JWT 集成

添加依賴:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

創(chuàng)建 JWT 工具類:

public class JwtTokenUtil {
    private String secret = "your-secret-key";
    private long expiration = 86400000; // 24小時
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        return Jwts.builder()
            .setClaims(claims)
            .setSubject(userDetails.getUsername())
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + expiration))
            .signWith(SignatureAlgorithm.HS512, secret)
            .compact();
    }
    public Boolean validateToken(String token, UserDetails userDetails) {
        final String username = getUsernameFromToken(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
    // 其他工具方法...
}

配置 JWT 過濾器:

public class JwtRequestFilter extends OncePerRequestFilter {
    @Autowired
    private CustomUserDetailsService userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        final String authorizationHeader = request.getHeader("Authorization");
        String username = null;
        String jwt = null;
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            username = jwtTokenUtil.getUsernameFromToken(jwt);
        }
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
            if (jwtTokenUtil.validateToken(jwt, userDetails)) {
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        chain.doFilter(request, response);
    }
}

在安全配置中添加過濾器:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .authorizeRequests()
            .antMatchers("/authenticate").permitAll()
            .anyRequest().authenticated()
        .and()
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}

5. 測試安全配置

5.1 測試控制器

@RestController
public class TestController {
    @GetMapping("/admin")
    @PreAuthorize("hasRole('ADMIN')")
    public String adminAccess() {
        return "Admin Board";
    }
    @GetMapping("/user")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public String userAccess() {
        return "User Content";
    }
    @GetMapping("/all")
    public String allAccess() {
        return "Public Content";
    }
}

5.2 測試安全配置

@SpringBootTest
@AutoConfigureMockMvc
public class SecurityTest {
    @Autowired
    private MockMvc mockMvc;
    @Test
    @WithMockUser(username = "user", roles = {"USER"})
    public void givenUserRole_whenAccessUserEndpoint_thenOk() throws Exception {
        mockMvc.perform(get("/user"))
            .andExpect(status().isOk());
    }
    @Test
    @WithMockUser(username = "user", roles = {"USER"})
    public void givenUserRole_whenAccessAdminEndpoint_thenForbidden() throws Exception {
        mockMvc.perform(get("/admin"))
            .andExpect(status().isForbidden());
    }
    @Test
    public void givenUnauthenticated_whenAccessPublicEndpoint_thenOk() throws Exception {
        mockMvc.perform(get("/all"))
            .andExpect(status().isOk());
    }
}

6. 最佳實踐

  1. 最小權(quán)限原則:只授予必要的權(quán)限
  2. 密碼安全:始終使用強(qiáng)密碼哈希算法(如 BCrypt)
  3. HTTPS:在生產(chǎn)環(huán)境中強(qiáng)制使用 HTTPS
  4. 安全頭:啟用安全頭(如 X-Frame-Options, X-XSS-Protection 等)
  5. 定期更新:保持 Spring Security 版本更新
  6. 審計日志:記錄重要的安全事件
  7. 輸入驗證:不要依賴 Spring Security 進(jìn)行所有輸入驗證

7. 常見問題解決

7.1 自定義登錄頁面

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/login*").permitAll()
            .anyRequest().authenticated()
        .and()
        .formLogin()
            .loginPage("/login.html")
            .loginProcessingUrl("/perform_login")
            .defaultSuccessUrl("/home.html", true)
            .failureUrl("/login.html?error=true");
}

7.2 處理 AccessDeniedException

創(chuàng)建自定義訪問拒絕處理器:

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
            AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.sendRedirect(request.getContextPath() + "/access-denied");
    }
}

然后在配置中使用:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .exceptionHandling()
            .accessDeniedHandler(accessDeniedHandler);
}

7.3 多 HTTP 安全配置

@Configuration
@Order(1)
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/api/**")
            .authorizeRequests()
                .anyRequest().hasRole("API_USER")
            .and()
            .httpBasic();
    }
}
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .formLogin();
    }
}

8. 總結(jié)

Spring Security 是一個功能全面且靈活的安全框架,本教程涵蓋了從基礎(chǔ)配置到高級特性的主要內(nèi)容。實際應(yīng)用中,應(yīng)根據(jù)具體需求選擇合適的認(rèn)證和授權(quán)方式,并遵循安全最佳實踐。

對于更復(fù)雜的場景,建議參考 Spring Security 官方文檔 和社區(qū)資源。

到此這篇關(guān)于Java中Spring Security的使用的文章就介紹到這了,更多相關(guān)Spring Security使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java注解Annotation與自定義注解詳解

    Java注解Annotation與自定義注解詳解

    本文全面講述了Java注解Annotation與Java自定義注解及相關(guān)內(nèi)容,大家可以認(rèn)真看看
    2018-03-03
  • Hadoop源碼分析六啟動文件namenode原理詳解

    Hadoop源碼分析六啟動文件namenode原理詳解

    本篇是Hadoop源碼分析系列文章第六篇,主要介紹Hadoop中的啟動文件namenode,后續(xù)本系列文章會持續(xù)更新,有需要的朋友可以借鑒參考下
    2021-09-09
  • Java中Map的九種遍歷方式總結(jié)

    Java中Map的九種遍歷方式總結(jié)

    日常工作中?Map?絕對是我們?Java?程序員高頻使用的一種數(shù)據(jù)結(jié)構(gòu),那?Map?都有哪些遍歷方式呢?這篇文章就帶大家看一下,看看你經(jīng)常使用的是哪一種
    2022-11-11
  • Java版C語言版簡單使用靜態(tài)語言實現(xiàn)動態(tài)數(shù)組的方法

    Java版C語言版簡單使用靜態(tài)語言實現(xiàn)動態(tài)數(shù)組的方法

    本文給大家分享java版和C語言版簡單使用靜態(tài)語言實現(xiàn)動態(tài)數(shù)組的方法,非常不錯,具有參考借鑒價值,需要的朋友參考下吧
    2017-10-10
  • java 代碼塊與靜態(tài)代碼塊加載順序

    java 代碼塊與靜態(tài)代碼塊加載順序

    這篇文章主要介紹了java 代碼塊與靜態(tài)代碼塊加載順序的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Java8 Comparator排序方法實例詳解

    Java8 Comparator排序方法實例詳解

    這篇文章主要介紹了Java8 Comparator排序方法實例詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • JavaApi實現(xiàn)更新刪除及讀取節(jié)點

    JavaApi實現(xiàn)更新刪除及讀取節(jié)點

    這篇文章主要介紹了JavaApi實現(xiàn)更新刪除及讀取節(jié)點,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • Java實現(xiàn)二分查找算法實例分析

    Java實現(xiàn)二分查找算法實例分析

    這篇文章主要介紹了Java實現(xiàn)二分查找算法,實例分析了二分查找算法的原理與相關(guān)實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • JavaTCP上傳圖片代碼實例

    JavaTCP上傳圖片代碼實例

    今天小編就為大家分享一篇關(guān)于JavaTCP上傳圖片代碼實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • 詳解Java中的阻塞隊列

    詳解Java中的阻塞隊列

    在去年的面試過程中,被面試官問道“阻塞隊列”這個問題,因為當(dāng)時并沒有對此問題進(jìn)行深入理解,只是按照自己的理解說明了該問題,最后面試結(jié)果也不太好,今天對該問題進(jìn)行簡要的面試并記錄如下;如有錯誤,歡迎指正,需要的朋友可以參考下
    2021-06-06

最新評論