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

Spring Security簡介、使用與最佳實(shí)踐

 更新時(shí)間:2025年09月10日 09:45:20   作者:妳人話  
Spring Security是一個(gè)能夠?yàn)榛赟pring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架,本文給大家介紹Spring Security使用與最佳實(shí)踐,感興趣的朋友跟隨小編一起看看吧

一、如何理解 Spring Security?—— 核心思想

        Spring Security 的核心是一個(gè)基于過濾器鏈(Filter Chain)的認(rèn)證和授權(quán)框架。不要把它想象成一個(gè)黑盒,而是一個(gè)可以高度定制和擴(kuò)展的安全衛(wèi)士。

  • 認(rèn)證 (Authentication - “你是誰?”)
    • 你進(jìn)入大樓,保安(Spring Security)要求你出示工牌和驗(yàn)證指紋(用戶名和密碼)。
    • 保安檢查工牌和指紋庫,確認(rèn)你是員工“張三”(驗(yàn)證憑證)。
    • 驗(yàn)證通過后,保安給你一張臨時(shí)門禁卡(Security Context / Token)。之后你在大樓里的活動(dòng),就靠這張卡來證明身份。
  • 授權(quán) (Authorization - “你能做什么?”)
    • 你拿著門禁卡,想進(jìn)入“財(cái)務(wù)室”。
    • 財(cái)務(wù)室門前的讀卡器(Spring Security 的授權(quán)管理器)檢查你的卡權(quán)限。
    • 發(fā)現(xiàn)你的卡只有“技術(shù)部”權(quán)限(角色:ROLE_DEV),而進(jìn)入“財(cái)務(wù)室”需要“財(cái)務(wù)部”權(quán)限(角色:ROLE_FINANCE)。
    • 讀卡器亮起紅燈,拒絕訪問(拋出 AccessDeniedException)。
  • 過濾器鏈 (Filter Chain) - “安保流程”
    • 整個(gè)大廈有一套嚴(yán)密的安保流程,每個(gè)環(huán)節(jié)都有一個(gè)專門的保安負(fù)責(zé):
  • 保安A:檢查你有沒有攜帶危險(xiǎn)品(CSRF 防護(hù)過濾器)。
  • 保安B:檢查你的門禁卡是否有效(認(rèn)證過濾器)。
  • 保安C:根據(jù)你的卡權(quán)限,決定你能去哪個(gè)房間(授權(quán)過濾器)。
    • 你的請(qǐng)求(你想進(jìn)入某個(gè)房間)必須按順序經(jīng)過所有這些保安的檢查,任何一個(gè)環(huán)節(jié)失敗都會(huì)被拒絕。Spring Security 就是這一整套保安流程的集合。

二、如何在 Java 項(xiàng)目中使用?—— 實(shí)戰(zhàn)步驟

我們以一個(gè)最常見的場(chǎng)景為例:使用數(shù)據(jù)庫存儲(chǔ)用戶信息,并實(shí)現(xiàn)基于角色(Role)的頁面訪問控制。

環(huán)境準(zhǔn)備

  • 創(chuàng)建項(xiàng)目:使用 Spring Initializr 創(chuàng)建一個(gè)新的 Spring Boot 項(xiàng)目,添加以下依賴:
    • Spring Web
    • Spring Security
    • Spring Data JPA
    • MySQL Driver (或 H2 Database 用于測(cè)試)
    • Thymeleaf (可選,用于前端頁面)
  • 配置數(shù)據(jù)庫:在 application.properties中配置數(shù)據(jù)源。
    • spring.datasource.url=jdbc:mysql://localhost:3306/your_database spring.datasource.username=root spring.datasource.password=your_password spring.jpa.hibernate.ddl-auto=update

步驟一:定義用戶和角色實(shí)體 (Entity)

@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name; // e.g., "ROLE_USER", "ROLE_ADMIN"
    // Constructors, getters, setters...
}
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private Boolean enabled;
    @ManyToMany(fetch = FetchType.EAGER) // 急加載,獲取用戶時(shí)立刻獲取角色
    @JoinTable(
        name = "users_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles = new HashSet<>();
    // Constructors, getters, setters...
}

步驟二:實(shí)現(xiàn) UserDetailsService - 連接數(shù)據(jù)庫和Security的橋梁

這是最關(guān)鍵的接口。Spring Security 會(huì)調(diào)用它的 loadUserByUsername 方法來根據(jù)用戶名獲取用戶信息。

@Service
public class MyUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository; // 你的JPA Repository
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1. 從數(shù)據(jù)庫查詢用戶
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found");
        }
        // 2. 將數(shù)據(jù)庫中的 User 對(duì)象,轉(zhuǎn)換為 Spring Security 認(rèn)識(shí)的 UserDetails 對(duì)象
        return org.springframework.security.core.userdetails.User
                .withUsername(user.getUsername())
                .password(user.getPassword())
                .disabled(!user.getEnabled())
                .authorities(getAuthorities(user.getRoles())) // 這里設(shè)置權(quán)限/角色
                .build();
    }
    // 將數(shù)據(jù)庫中的 Role 集合轉(zhuǎn)換為 Spring Security 認(rèn)識(shí)的 GrantedAuthority 集合
    private Collection<? extends GrantedAuthority> getAuthorities(Set<Role> roles) {
        return roles.stream()
                .map(role -> new SimpleGrantedAuthority(role.getName()))
                .collect(Collectors.toList());
    }
}

步驟三:安全配置類 (Security Configuration) - 核心配置

這是你定義安全規(guī)則的地方:哪些URL需要保護(hù)?誰可以訪問?登錄/登出怎么處理?

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private MyUserDetailsService userDetailsService;
    // 配置密碼編碼器。Spring Security 強(qiáng)制要求密碼必須加密。
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // 授權(quán)配置:定義哪些請(qǐng)求需要什么權(quán)限
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/", "/home", "/public/**").permitAll() // 允許所有人訪問
                .requestMatchers("/admin/**").hasRole("ADMIN") // 只有ADMIN角色可以訪問
                .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN") // USER或ADMIN角色可以訪問
                .anyRequest().authenticated() // 所有其他請(qǐng)求都需要認(rèn)證(登錄)
            )
            // 表單登錄配置
            .formLogin(form -> form
                .loginPage("/login") // 自定義登錄頁面路徑
                .permitAll() // 允許所有人訪問登錄頁面
                .defaultSuccessUrl("/dashboard") // 登錄成功后的默認(rèn)跳轉(zhuǎn)頁面
            )
            // 登出配置
            .logout(logout -> logout
                .permitAll()
                .logoutSuccessUrl("/login?logout") // 登出成功后跳轉(zhuǎn)的頁面
            )
            // 記住我功能
            .rememberMe(remember -> remember
                .key("uniqueAndSecret") // 用于對(duì) token 進(jìn)行哈希的密鑰
                .tokenValiditySeconds(86400) // 記住我有效期為1天
            )
            // 異常處理:權(quán)限不足時(shí)
            .exceptionHandling(handling -> handling
                .accessDeniedPage("/access-denied")
            )
            // 關(guān)鍵:配置自定義的 UserDetailsService
            .userDetailsService(userDetailsService);
        return http.build();
    }
}

步驟四:控制器和視圖 (Controller & View)

@Controller
public class HomeController {
    @GetMapping("/")
    public String home() {
        return "home"; // home.html
    }
    @GetMapping("/admin/dashboard")
    public String adminDashboard() {
        return "admin-dashboard";
    }
    @GetMapping("/user/dashboard")
    public String userDashboard() {
        return "user-dashboard";
    }
    @GetMapping("/login")
    public String login() {
        return "login";
    }
    @GetMapping("/access-denied")
    public String accessDenied() {
        return "access-denied";
    }
}

在 templates/login.html 中,你需要一個(gè)符合 Spring Security 約定的表單:

<form th:action="@{/login}" method="post">
    <input type="text" name="username" placeholder="Username"/>
    <input type="password" name="password" placeholder="Password"/>
    <input type="checkbox" name="remember-me"/> Remember Me
    <button type="submit">Login</button>
</form>

注意th:action="@{/login}"name="username"、name="password" 都是默認(rèn)的,不能隨意更改。

步驟五:在視圖和控制器中獲取用戶信息

// 在Controller中獲取當(dāng)前用戶
@GetMapping("/profile")
public String profile(Model model) {
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    if (principal instanceof UserDetails) {
        String username = ((UserDetails) principal).getUsername();
        model.addAttribute("username", username);
    }
    return "profile";
}
// 更優(yōu)雅的方式:使用 Principal 對(duì)象直接注入
@GetMapping("/profile2")
public String profile2(Principal principal, Model model) {
    model.addAttribute("username", principal.getName());
    return "profile";
}

在 Thymeleaf 模板中,可以直接使用 Securty 表達(dá)式:

<div th:if="${#authorization.expression('isAuthenticated()')}">
    <p>Welcome, <span th:text="${#authentication.name}">User</span>!</p>
    <p>You have roles: <span th:text="${#authentication.authorities}">[]</span></p>
</div>

總結(jié)與最佳實(shí)踐

  • 密碼必須編碼:永遠(yuǎn)不要用明文存儲(chǔ)密碼。BCryptPasswordEncoder 是當(dāng)前的首選。
  • 最小權(quán)限原則:只授予用戶完成其工作所必需的最小權(quán)限。
  • 縱深防御:不要只依賴 Spring Security。在服務(wù)層方法上也可以使用 @PreAuthorize 注解進(jìn)行二次校驗(yàn)。
@PreAuthorize("hasRole('ADMIN') or #userId == authentication.principal.id")
public User getUserById(Long userId) { ... }
  • 保持更新:Spring Security 本身和其依賴庫可能會(huì)發(fā)現(xiàn)漏洞,定期更新版本。

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

相關(guān)文章

  • 初識(shí)Java一些常見的數(shù)據(jù)類型

    初識(shí)Java一些常見的數(shù)據(jù)類型

    這篇文章主要介紹Java一些常見的數(shù)據(jù)類型,Java是一種優(yōu)秀的程序設(shè)計(jì)語言,它具有令人賞心悅目的語法和易于理解的語義,下面文章小編就來簡單介紹為什么說Java是最好的語言并且介紹它的各種常見類型,需要的朋友可以參考一下
    2021-10-10
  • SpringBoot 使用Mongo的GridFs實(shí)現(xiàn)分布式文件存儲(chǔ)操作

    SpringBoot 使用Mongo的GridFs實(shí)現(xiàn)分布式文件存儲(chǔ)操作

    這篇文章主要介紹了Spring Boot 使用Mongo的GridFs實(shí)現(xiàn)分布式文件存儲(chǔ)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • springcloud 熔斷器Hystrix的具體使用

    springcloud 熔斷器Hystrix的具體使用

    本篇文章主要介紹了springcloud 熔斷器Hystrix的具體使用,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-02-02
  • 200行Java代碼如何實(shí)現(xiàn)依賴注入框架詳解

    200行Java代碼如何實(shí)現(xiàn)依賴注入框架詳解

    依賴注入對(duì)大家來說應(yīng)該都不陌生,下面這篇文章主要給大家介紹了關(guān)于利用200行Java代碼如何實(shí)現(xiàn)依賴注入框架的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-05-05
  • Java基礎(chǔ)將Bean屬性值放入Map中的實(shí)例

    Java基礎(chǔ)將Bean屬性值放入Map中的實(shí)例

    這篇文章主要介紹了Java基礎(chǔ)將Bean屬性值放入Map中的實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Java中Arrays類與Math類詳解

    Java中Arrays類與Math類詳解

    這篇文章主要介紹了Java中Arrays類與Math類,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 使用java生成激活碼和密鑰的方法

    使用java生成激活碼和密鑰的方法

    本文主要介紹了java生成激活碼和密鑰的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • Spring Boot Admin郵件警報(bào)整合過程解析

    Spring Boot Admin郵件警報(bào)整合過程解析

    這篇文章主要介紹了Spring Boot Admin郵件警報(bào)整合過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • SpringBoot中的統(tǒng)一異常處理詳細(xì)解析

    SpringBoot中的統(tǒng)一異常處理詳細(xì)解析

    這篇文章主要介紹了SpringBoot中的統(tǒng)一異常處理詳細(xì)解析,該注解可以把異常處理器應(yīng)用到所有控制器,而不是單個(gè)控制器,借助該注解,我們可以實(shí)現(xiàn):在獨(dú)立的某個(gè)地方,比如單獨(dú)一個(gè)類,定義一套對(duì)各種異常的處理機(jī)制,需要的朋友可以參考下
    2024-01-01
  • SpringBoot整合MyBatis和MyBatis-Plus請(qǐng)求后不打印sql日志的問題解決

    SpringBoot整合MyBatis和MyBatis-Plus請(qǐng)求后不打印sql日志的問題解決

    本文主要介紹了SpringBoot整合MyBatis和MyBatis-Plus請(qǐng)求后不打印sql日志的問題解決文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-07-07

最新評(píng)論