最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Security簡介、使用與最佳實踐

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

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

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

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

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

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

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

  • 創(chuàng)建項目:使用 Spring Initializr 創(chuàng)建一個新的 Spring Boot 項目,添加以下依賴:
    • Spring Web
    • Spring Security
    • Spring Data JPA
    • MySQL Driver (或 H2 Database 用于測試)
    • 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

步驟一:定義用戶和角色實體 (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) // 急加載,獲取用戶時立刻獲取角色
    @JoinTable(
        name = "users_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles = new HashSet<>();
    // Constructors, getters, setters...
}

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

這是最關(guān)鍵的接口。Spring Security 會調(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 對象,轉(zhuǎn)換為 Spring Security 認識的 UserDetails 對象
        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 認識的 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需要保護?誰可以訪問?登錄/登出怎么處理?

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private MyUserDetailsService userDetailsService;
    // 配置密碼編碼器。Spring Security 強制要求密碼必須加密。
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // 授權(quán)配置:定義哪些請求需要什么權(quán)限
            .authorizeHttpRequests(authz -> authz
                .requestMatchers("/", "/home", "/public/**").permitAll() // 允許所有人訪問
                .requestMatchers("/admin/**").hasRole("ADMIN") // 只有ADMIN角色可以訪問
                .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN") // USER或ADMIN角色可以訪問
                .anyRequest().authenticated() // 所有其他請求都需要認證(登錄)
            )
            // 表單登錄配置
            .formLogin(form -> form
                .loginPage("/login") // 自定義登錄頁面路徑
                .permitAll() // 允許所有人訪問登錄頁面
                .defaultSuccessUrl("/dashboard") // 登錄成功后的默認跳轉(zhuǎn)頁面
            )
            // 登出配置
            .logout(logout -> logout
                .permitAll()
                .logoutSuccessUrl("/login?logout") // 登出成功后跳轉(zhuǎn)的頁面
            )
            // 記住我功能
            .rememberMe(remember -> remember
                .key("uniqueAndSecret") // 用于對 token 進行哈希的密鑰
                .tokenValiditySeconds(86400) // 記住我有效期為1天
            )
            // 異常處理:權(quán)限不足時
            .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 中,你需要一個符合 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" 都是默認的,不能隨意更改。

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

// 在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 對象直接注入
@GetMapping("/profile2")
public String profile2(Principal principal, Model model) {
    model.addAttribute("username", principal.getName());
    return "profile";
}

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

<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é)與最佳實踐

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

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

相關(guān)文章

最新評論

泗水县| 姜堰市| 揭东县| 焉耆| 沾益县| 彩票| 万全县| 滨海县| 八宿县| 随州市| 南丹县| 湖南省| 启东市| 蚌埠市| 舞阳县| 杭锦旗| 清镇市| 韶关市| 新建县| 陵川县| 惠水县| 内黄县| 女性| 成都市| 舒兰市| 淳化县| 微山县| 无极县| 保康县| 嘉义市| 罗源县| 乌兰县| 岳阳市| 尉犁县| 明水县| 景洪市| 龙门县| 南木林县| 南雄市| 册亨县| 星座|