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

Spring?Security入門(mén)到深入實(shí)戰(zhàn)步驟詳解

 更新時(shí)間:2025年11月25日 08:46:12   作者:佛祖讓我來(lái)巡山  
小明通過(guò)學(xué)習(xí)SpringSecurity,成功為自己的攝影網(wǎng)站添加了完整的登錄認(rèn)證鑒權(quán)功能,包括自定義用戶存儲(chǔ)、權(quán)限控制、自定義登錄頁(yè)、JWT集成以及OAuth2第三方登錄,并且對(duì)SpringSecurity有了深入的理解和認(rèn)識(shí),喜歡的朋友跟隨小編一起學(xué)習(xí)吧

小 明 的 攝 影 網(wǎng) 站 已 經(jīng) 用 Spring Boot 搭 建 完 成 , 訪 客 越 來(lái) 越 多 。 他 決 定 給 網(wǎng) 站 加 上 完 整 的 登 錄 認(rèn) 證 鑒 權(quán) 功 能 , 讓 不 同 角 色 的 用 戶 ( 游 客 、 編 輯 、 管 理 員 ) 有 不 同 的 操 作 權(quán) 限 。 今 天 , 他 就 帶 著 這 個(gè) 需 求 , 開(kāi) 啟 Spring Security 的 學(xué) 習(xí) 之 旅 。

** 第 一 步 : 搭 建 Spring Boot 項(xiàng) 目 , 引 入 Spring Security **

** 小 明 的 需 求 **

“ 先 讓 網(wǎng) 站 有 個(gè) 最 基 礎(chǔ) 的 登 錄 功 能 , 能 攔 住 未 登 錄 的 用 戶 。 ”

** 實(shí) 操 步 驟 **

  • ** 創(chuàng) 建 Spring Boot 項(xiàng) 目 ** : 用 https://start.spring.io/ , 選 Spring Web ( 搭 Web 服 務(wù) ) 、 Spring Security ( 安 全 框 架 ) 、 Spring Data JPA ( 操 作 數(shù) 據(jù) 庫(kù) ) 、 MySQL Driver ( 數(shù) 據(jù) 庫(kù) 驅(qū) 動(dòng) ) 。
  • ** 添 加 依 賴 ** ( pom.xml 核 心 部 分 ) :
<dependencies>  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-web</artifactId>  
    </dependency>  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-security</artifactId>  <!--  Spring Security  依  賴  -->  
    </dependency>  
    <dependency>  
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-data-jpa</artifactId>  
    </dependency>  
    <dependency>  
        <groupId>com.mysql</groupId>  
        <artifactId>mysql-connector-j</artifactId>  
    </dependency>  
</dependencies>  
  • ** 運(yùn) 行 項(xiàng) 目 ** : 啟 動(dòng) Spring Boot , 訪 問(wèn) http://localhost:8080 , 會(huì) 自 動(dòng) 跳 轉(zhuǎn) 到 Spring Security 的 默 認(rèn) 登 錄 頁(yè) 。

** 現(xiàn) 象 與 原 理 **

  • ** 默 認(rèn) 用 戶 ** : 控 制 臺(tái) 會(huì) 打 印 一 行 密 碼 , 格 式 如 Using generated security password: abcdef12-3456-7890-abcd-ef1234567890 , 用 戶 名 固 定 為 user 。
  • ** 原 理 ** : Spring Security 自 動(dòng) 配 置 了 默 認(rèn) 的 InMemoryUserDetailsManager ( 內(nèi) 存 用 戶 存 儲(chǔ) ) , 生 成 隨 機(jī) 密 碼 。 所 有 接 口 默 認(rèn) 需 要 USER 角 色 才 能 訪 問(wèn) 。

?? 小 明 的 疑 問(wèn) : “ 這 密 碼 每 次 啟 動(dòng) 都 變 , 而 且 用 戶 不 能 自 己 注 冊(cè) , 得 改 ! ”

** 第 二 步 : 自 定 義 用 戶 存 儲(chǔ) —— 從 內(nèi) 存 到 數(shù) 據(jù) 庫(kù) **

** 小 明 的 需 求 **

“ 用 戶 信 息 存 在 自 己 的 數(shù) 據(jù) 庫(kù) 里 , 支 持 注 冊(cè) 、 登 錄 , 密 碼 用 BCrypt 加 密 。 ”

** 核 心 概 念 **

  • ** UserDetailsService ** : Spring Security 的 “ 用 戶 查 詢 接 口 ” , 開(kāi) 發(fā) 者 實(shí) 現(xiàn) 它 , 告 訴 框 架 “ 怎 么 從 數(shù) 據(jù) 庫(kù) 查 用 戶 ” 。
  • ** UserDetails ** : “ 用 戶 信 息 封 裝 類 ” , 包 含 用 戶 名 、 密 碼 、 角 色 、 賬 戶 是 否 過(guò) 期 等 信 息 。
  • ** PasswordEncoder ** : “ 密 碼 加 密 器 ” , 用 BCrypt 算 法 把 明 文 密 碼 變 成 哈 希 值 存 儲(chǔ) 。

** 實(shí) 操 步 驟 **

** 建 用 戶 表 ** ( MySQL ) :

CREATE TABLE users (  
    id BIGINT AUTO_INCREMENT PRIMARY KEY,  
    username VARCHAR(50) UNIQUE NOT NULL,  --  用  戶  名  
    password VARCHAR(100) NOT NULL,         --  BCrypt  哈  希  后  的  密  碼  
    role VARCHAR(20) NOT NULL               --  角  色  :  ROLE_VISITOR  /  ROLE_EDITOR  /  ROLE_ADMIN  
);  

** 實(shí) 現(xiàn) UserDetailsService ** ( 查 數(shù) 據(jù) 庫(kù) 用 戶 ) :

@Service  
public class CustomUserDetailsService implements UserDetailsService {  
    @Autowired private UserRepository userRepo;  //  JPA  操  作  users  表  
    @Override  
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {  
        //  1.  查  數(shù)  據(jù)  庫(kù)  用  戶  
        User user = userRepo.findByUsername(username)  
            .orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));  
        //  2.  封  裝  成  UserDetails  對(duì)  象  (  Spring Security  認(rèn)  識(shí)  的  格  式  )  
        return org.springframework.security.core.userdetails.User.builder()  
            .username(user.getUsername())  
            .password(user.getPassword())  //  存  的  是  BCrypt  哈  希  值  
            .roles(user.getRole().replace("ROLE_", ""))  //  角  色  去  掉  ROLE_  前  綴  
            .build();  
    }  
}  

** 配 置 PasswordEncoder ** ( 用 BCrypt 加 密 ) :

@Configuration  
public class SecurityConfig {  
    @Bean  
    public PasswordEncoder passwordEncoder() {  
        return new BCryptPasswordEncoder();  //  BCrypt  加  密  器  ,  自  帶  隨  機(jī)  鹽  
    }  
}  

** 注 冊(cè) 用 戶 ** ( 比 如 小 明 自 己 注 冊(cè) 為 管 理 員 ) :

@RestController  
public class RegisterController {  
    @Autowired private UserRepository userRepo;  
    @Autowired private PasswordEncoder passwordEncoder;  
    @PostMapping("/register")  
    public String register(String username, String rawPassword, String role) {  
        User user = new User();  
        user.setUsername(username);  
        user.setPassword(passwordEncoder.encode(rawPassword));  //  明  文  密  碼  →  BCrypt  哈  希  
        user.setRole("ROLE_" + role.toUpperCase());  //  角  色  加  ROLE_  前  綴  (  Spring Security  約  定  )  
        userRepo.save(user);  
        return "注冊(cè)成功!";  
    }  
}  

** 效 果 **

小 明 用 POST /register?username=xiaoming&rawPassword=123456&role=admin 注 冊(cè) 后 , 數(shù) 據(jù) 庫(kù) users 表 會(huì) 存 一 條 記 錄 , password 字 段 是 BCrypt 哈 希 值 ( 如 $2a$10$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx )。 登 錄 時(shí) , 框 架 會(huì) 用 BCrypt 驗(yàn) 證 輸 入 密 碼 是 否 匹 配 。

?? 小 明 的 體 會(huì) : “ UserDetailsService 就 像 圖 書(shū) 館 的 ‘ 查 閱 員 ’ , 框 架 告 訴 他 ‘ 找 小 明 ’ , 他 就 去 數(shù) 據(jù) 庫(kù) 把 小 明 的 書(shū) ( 用 戶 信 息 ) 拿 回 來(lái) 。 ”

** 第 三 步 : 配 置 權(quán) 限 控 制 —— 誰(shuí) 能 干 啥 ? **

** 小 明 的 需 求 **

“ 游 客 只 能 看 照 片 , 編 輯 能 上 傳 , 管 理 員 能 刪 除 。 ”

** 核 心 概 念 **

  • ** HttpSecurity ** : Spring Security 的 “ Web 安 全 配 置 類 ” , 用 來(lái) 設(shè) 置 URL 訪 問(wèn) 權(quán) 限 、 登 錄 / 注 銷 頁(yè) 、 CSRF 等 。
  • ** @PreAuthorize ** : “ 方 法 級(jí) 權(quán) 限 注 解 ” , 直 接 在 Controller 方 法 上 標(biāo) 注 需 要 的 角 色 。

** 實(shí) 操 步 驟 **

** 配 置 URL 訪 問(wèn) 權(quán) 限 ** ( 在 SecurityConfig 中 ) :

@Configuration  
@EnableWebSecurity  //  開(kāi)  啟  Web  安  全  配  置  
public class SecurityConfig {  
    @Autowired private CustomUserDetailsService userDetailsService;  
    @Autowired private PasswordEncoder passwordEncoder;  

    @Bean  
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {  
        http  
            .authorizeHttpRequests(auth -&gt; auth  
                .requestMatchers("/photos/**").permitAll()  //  公  開(kāi)  :  所  有  人  能  看  照  片  
                .requestMatchers("/upload/**").hasRole("EDITOR")  //  上  傳  :  需  EDITOR  角  色  
                .requestMatchers("/delete/**").hasRole("ADMIN")  //  刪  除  :  需  ADMIN  角  色  
                .anyRequest().authenticated()  //  其  他  接  口  需  登  錄  
            )  
            .formLogin(form -&gt; form  //  配  置  登  錄  頁(yè)  
                .loginPage("/my-login")  //  自  定  義  登  錄  頁(yè)  (  下  節(jié)  講  )  
                .defaultSuccessUrl("/home")  //  登  錄  成  功  跳  轉(zhuǎn)  
            )  
            .logout(logout -&gt; logout  //  配  置  注  銷  
                .logoutUrl("/logout")  
                .logoutSuccessUrl("/photos")  
            );  
        return http.build();  
    }  

    //  配  置  認(rèn)  證  管  理  器  (  用  自  定  義  UserDetailsService  和  PasswordEncoder  )  
    @Bean  
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {  
        return config.getAuthenticationManager();  
    }  
}  

** 用 @PreAuthorize 做 方 法 級(jí) 權(quán) 限 ** ( 更 精 細(xì) 控 制 ) :

@RestController  
public class PhotoController {  
    //  游  客  能  看  
    @GetMapping("/photos")  
    public List<Photo> listPhotos() { ... }  
    //  編  輯  能  上  傳  (  @PreAuthorize  需  開(kāi)  啟  @EnableMethodSecurity  )  
    @PostMapping("/upload")  
    @PreAuthorize("hasRole('EDITOR')")  //  直  接  標(biāo)  注  需  EDITOR  角  色  
    public String uploadPhoto(MultipartFile file) { ... }  
    //  管  理  員  能  刪  除  
    @DeleteMapping("/delete/{id}")  
    @PreAuthorize("hasRole('ADMIN') or hasRole('EDITOR')")  //  管  理  員  或  編  輯  都  能  刪  
    public String deletePhoto(@PathVariable Long id) { ... }  
}  
  • ** 開(kāi) 啟 @PreAuthorize 支 持 ** : 在 SecurityConfig 上 加 @EnableMethodSecurity 。

** 效 果 **

  • 訪 問(wèn) /upload 時(shí) , 若 用 戶 是 ROLE_VISITOR , 會(huì) 被 攔 截 并 返 回 403 錯(cuò) 誤 ( 權(quán) 限 不 足 ) ;
  • 用 @PreAuthorize 的 方 法 , 框 架 會(huì) 在 執(zhí) 行 前 檢 查 用 戶 角 色 , 不 符 合 則 拋 異 常 。

?? 小 明 的 體 會(huì) : “ HttpSecurity 像 ‘ 門(mén) 衛(wèi) ’ , 管 URL 級(jí) 的 大 門(mén) ; @PreAuthorize 像 ‘ 房 間 鎖 ’ , 管 方 法 級(jí) 的 小 門(mén) , 雙 保 險(xiǎn) ! ”

** 第 四 步 : 自 定 義 登 錄 頁(yè) 、 注 銷 與 記 住 我 **

** 小 明 的 需 求 **

“ 默 認(rèn) 登 錄 頁(yè) 太 丑 , 想 用 自 己 的 ; 加 個(gè) ‘ 記 住 我 ’ 功 能 , 關(guān) 閉 瀏 覽 器 再 打 開(kāi) 還 是 登 錄 狀 態(tài) 。 ”

** 實(shí) 操 步 驟 **

  • ** 自 定 義 登 錄 頁(yè) ** :
    • 寫(xiě) 一 個(gè) HTML 頁(yè) 面 my-login.html ( 放 resources/templates 目 錄 ) , 包 含 username 、 password 輸 入 框 和 remember-me 復(fù) 選 框 ;
    • 在 SecurityConfig 中 配 置 .loginPage("/my-login") , 并 指 定 處 理 登 錄 的 URL :
    .formLogin(form -> form  
        .loginPage("/my-login")  //  自  定  義  登  錄  頁(yè)  路  徑  
        .loginProcessingUrl("/do-login")  //  處  理  登  錄  的  URL  (  框  架  自  動(dòng)  處  理  )  
        .defaultSuccessUrl("/home")  
        .failureUrl("/my-login?error")  //  登  錄  失  敗  跳  轉(zhuǎn)  
    )  
  • ** 開(kāi) 啟 “ 記 住 我 ” 功 能 ** :
    • 在 SecurityConfig 中 配 置 .rememberMe() :
    .rememberMe(remember -> remember  
        .key("xiaoming-secret-key")  //  自  定  義  密  鑰  (  防  篡  改  )  
        .tokenValiditySeconds(7 * 24 * 3600)  //  記  住  我  有  效  期  :  7  天  
    )  
    • 在 自 定 義 登 錄 頁(yè) 加 “ 記 住 我 ” 復(fù) 選 框 :
    <input type="checkbox" name="remember-me"> 記住我  
  • ** 自 定 義 注 銷 頁(yè) ** :
    • 在 SecurityConfig 中 配 置 .logout() , 默 認(rèn) 注 銷 URL 是 /logout , 可 自 定 義 :
    .logout(logout -> logout  
        .logoutUrl("/my-logout")  //  自  定  義  注  銷  URL  
        .logoutSuccessUrl("/photos")  //  注  銷  成  功  跳  轉(zhuǎn)  
        .invalidateHttpSession(true)  //  注  銷  時(shí)  清  空  Session  
        .deleteCookies("JSESSIONID")  //  刪  除  Cookie  
    )  

** 效 果 **

  • 訪 問(wèn) 需 登 錄 的 頁(yè) 面 時(shí) , 跳 轉(zhuǎn) 到 小 明 自 己 寫(xiě) 的 my-login.html ;
  • 勾 選 “ 記 住 我 ” 后 , 關(guān) 閉 瀏 覽 器 , 7 天 內(nèi) 再 訪 問(wèn) 網(wǎng) 站 仍 是 登 錄 狀 態(tài) ;
  • 點(diǎn) 擊 注 銷 鏈 接 , 清 空 Session 和 Cookie , 跳 回 公 開(kāi) 照 片 頁(yè) 。

?? 小 明 的 體 會(huì) : “ 自 定 義 登 錄 頁(yè) 讓 網(wǎng) 站 更 好 看 , ‘ 記 住 我 ’ 像 ‘ 長(zhǎng) 期 飯 卡 ’ , 不 用 每 次 都 刷 臨 時(shí) 卡 。 ”

** 第 五 步 : 集 成 JWT —— 支 持 APP 與 微 服 務(wù) **

** 小 明 的 需 求 **

“ 我 做 了 個(gè) 手 機(jī) APP , 用 Session - Cookie 不 方 便 , 想 用 JWT Token 做 認(rèn) 證 。 ”

** 核 心 概 念 **

  • ** JWT ** : “ 自 帶 信 息 的 身 份 證 ” , 服 務(wù) 器 不 存 Session , 用 戶 登 錄 后 拿 Token , 后 續(xù) 請(qǐng) 求 帶 Token 即 可 。
  • ** JwtAuthenticationFilter ** : 自 定 義 過(guò) 濾 器 , 從 Authorization 頭 取 JWT , 驗(yàn) 證 后 設(shè) 置 Security Context 。

** 實(shí) 操 步 驟 **

  • ** 添 加 JWT 依 賴 ** :
    <dependency>  
        <groupId>io.jsonwebtoken</groupId>  
        <artifactId>jjwt-api</artifactId>  
        <version>0.11.5</version>  
    </dependency>  
    <dependency>  
        <groupId>io.jsonwebtoken</groupId>  
        <artifactId>jjwt-impl</artifactId>  
        <version>0.11.5</version>  
        <scope>runtime</scope>  
    </dependency>  
    <dependency>  
        <groupId>io.jsonwebtoken</groupId>  
        <artifactId>jjwt-jackson</artifactId>  
        <version>0.11.5</version>  
        <scope>runtime</scope>  
    </dependency>  
  • ** 寫(xiě) JWT 工 具 類 ** ( 生 成 / 驗(yàn) 證 Token ) :
    @Component  
    public class JwtUtil {  
        @Value("${jwt.secret}") private String secret;  //  配  置  在  application.properties  中  
        @Value("${jwt.expiration}") private long expiration;  //  Token  有  效  期  (  如  3600000  毫  秒  )  
        //  生  成  Token  
        public String generateToken(UserDetails userDetails) {  
            Map<String, Object> claims = new HashMap<>();  
            claims.put("roles", userDetails.getAuthorities().stream()  
                .map(GrantedAuthority::getAuthority).collect(Collectors.toList()));  
            return Jwts.builder()  
                .setClaims(claims)  
                .setSubject(userDetails.getUsername())  
                .setIssuedAt(new Date())  
                .setExpiration(new Date(System.currentTimeMillis() + expiration))  
                .signWith(SignatureAlgorithm.HS512, secret)  //  用  HS512  算  法  簽  名  
                .compact();  
        }  
        //  驗(yàn)  證  Token  并  取  用  戶  名  
        public String getUsernameFromToken(String token) {  
            return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject();  
        }  
    }  
  • ** 寫(xiě) JWT 認(rèn) 證 過(guò) 濾 器 ** :
    public class JwtAuthenticationFilter extends OncePerRequestFilter {  
        @Autowired private JwtUtil jwtUtil;  
        @Autowired private CustomUserDetailsService userDetailsService;  
        @Override  
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {  
            //  1.  從  Header  取  Token  
            String token = request.getHeader("Authorization");  
            if (token != null && token.startsWith("Bearer ")) {  
                token = token.substring(7);  
                //  2.  驗(yàn)  證  Token  ,  取  用  戶  名  
                String username = jwtUtil.getUsernameFromToken(token);  
                if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {  
                    //  3.  查  用  戶  信  息  ,  設(shè)  置  Security Context  
                    UserDetails userDetails = userDetailsService.loadUserByUsername(username);  
                    UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(  
                        userDetails, null, userDetails.getAuthorities());  
                    SecurityContextHolder.getContext().setAuthentication(auth);  
                }  
            }  
            chain.doFilter(request, response);  //  繼  續(xù)  處  理  請(qǐng)  求  
        }  
    }  
  • ** 修 改 SecurityConfig , 用 JWT 替 換 Session ** :
    @Bean  
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {  
        http  
            .csrf(csrf -> csrf.disable())  //  JWT  無(wú)  狀  態(tài)  ,  關(guān)  閉  CSRF  
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))  //  無(wú)  Session  
            .authorizeHttpRequests(auth -> auth  
                .requestMatchers("/api/photos/**").permitAll()  
                .requestMatchers("/api/upload/**").hasRole("EDITOR")  
                .anyRequest().authenticated()  
            )  
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)  //  加  JWT  過(guò)  濾  器  
            .formLogin(form -> form.disable())  //  禁  用  默  認(rèn)  表  單  登  錄  (  APP  用  JWT  )  
            .logout(logout -> logout.disable());  //  禁  用  默  認(rèn)  注  銷  
        return http.build();  
    }  

** 效 果 **

  • APP 用 戶 登 錄 時(shí) , 調(diào) POST /api/login ( 自 定 義 接 口 , 驗(yàn) 證 用 戶 名 密 碼 后 返 JWT ) ;
  • 后 續(xù) APP 請(qǐng) 求 API 時(shí) , 在 Authorization 頭 帶 Bearer <JWT> , 框 架 自 動(dòng) 認(rèn) 證 。

?? 小 明 的 體 會(huì) : “ JWT 像 ‘ 電 子 通 行 證 ’ , APP 拿 著 它 就 能 暢 通 無(wú) 阻 , 服 務(wù) 器 不 用 記 住 誰(shuí) 來(lái) 過(guò) , 輕 松 支 持 多 端 ! ”

** 第 六 步 : 深 入 : OAuth2 第 三 方 登 錄 與 安 全 防 護(hù) **

** 小 明 的 需 求 **

“ 想 讓 用 戶 用 GitHub 賬 號(hào) 直 接 登 錄 , 還 要 防 CSRF 、 XSS 攻 擊 。 ”

** 核 心 概 念 **

  • ** OAuth2 ** : “ 第 三 方 登 錄 協(xié) 議 ” , 用 戶 授 權(quán) GitHub 告 訴 小 明 的 網(wǎng) 站 “ 這 是 我 ” , 無(wú) 需 注 冊(cè) 。
  • ** Spring Security OAuth2 Client ** : 框 架 內(nèi) 置 OAuth2 客 戶 端 , 支 持 GitHub 、 Google 等 登 錄 。

** 實(shí) 操 步 驟 **

  • ** 配 置 GitHub OAuth2 登 錄 ** :
    • 在 GitHub 開(kāi) 發(fā) 者 設(shè) 置 中 創(chuàng) 建 OAuth App , 獲 取 client-id 和 client-secret ;
    • 在 application.properties 中 配 置 :
    spring.security.oauth2.client.registration.github.client-id=你的client-id  
    spring.security.oauth2.client.registration.github.client-secret=你的client-secret  
    spring.security.oauth2.client.registration.github.scope=user:email  #  申  請(qǐng)  郵  箱  權(quán)  限  
    • 在 SecurityConfig 中 開(kāi) 啟 OAuth2 登 錄 :
    .oauth2Login(oauth2 -> oauth2  
        .loginPage("/my-login")  //  自  定  義  登  錄  頁(yè)  加  “  GitHub  登  錄  ”  按  鈕  
        .defaultSuccessUrl("/home")  
    )  
  • ** 安 全 防 護(hù) ** ( 框 架 默 認(rèn) 開(kāi) 啟 , 無(wú) 需 額 外 配 置 ) :
    • ** CSRF 防 護(hù) ** : 默 認(rèn) 開(kāi) 啟 , 框 架 自 動(dòng) 生 成 CSRF 令 牌 , 表 單 提 交 時(shí) 驗(yàn) 證 ;
    • ** XSS 防 護(hù) ** : Spring Boot 默 認(rèn) 開(kāi) 啟 HTML 轉(zhuǎn) 義 , 防 注 入 腳 本 ;
    • ** 會(huì) 話 固 定 攻 擊 防 護(hù) ** : 登 錄 后 自 動(dòng) 更 換 SessionID 。

** 效 果 **

  • 小 明 的 登 錄 頁(yè) 多 了 個(gè) “ 用 GitHub 登 錄 ” 按 鈕 , 點(diǎn) 擊 后 跳 轉(zhuǎn) GitHub 授 權(quán) , 授 權(quán) 成 功 后 自 動(dòng) 登 錄 網(wǎng) 站 ;
  • 框 架 自 動(dòng) 擋 住 CSRF 攻 擊 , 即 使 黑 客 誘 騙 小 明 點(diǎn) 鏈 接 , 也 無(wú) 法 操 作 。

?? 小 明 的 體 會(huì) : “ OAuth2 像 ‘ 找 朋 友 作 證 ’ , 讓 GitHub 幫 忙 證 明 ‘ 這 是 小 明 ’ ; 框 架 的 安 全 防 護(hù) 像 ‘ 隱 形 鎧 甲 ’ , 平 時(shí) 感 覺(jué) 不 到 , 關(guān) 鍵 時(shí) 刻 能 擋 刀 。 ”

** 小 明 的 學(xué) 習(xí) 總 結(jié) **

通 過(guò) 這 幾 步 , 小 明 徹 底 掌 握 了 Spring Security 配 Spring Boot 的 核 心 用 法 :

  • ** 從 默 認(rèn) 配 置 入 門(mén) ** , 觀 察 框 架 自 動(dòng) 生 成 的 登 錄 / 權(quán) 限 邏 輯 ;
  • ** 自 定 義 UserDetailsService 和 PasswordEncoder ** , 連 接 自 己 的 數(shù) 據(jù) 庫(kù) , 用 BCrypt 加 密 密 碼 ;
  • ** 用 HttpSecurity 和 @PreAuthorize 配 置 權(quán) 限 ** , 實(shí) 現(xiàn) URL 級(jí) 和 方 法 級(jí) 控 制 ;
  • ** 自 定 義 登 錄 / 注 銷 頁(yè) 、 加 “ 記 住 我 ” ** , 優(yōu) 化 用 戶 體 驗(yàn) ;
  • ** 集 成 JWT ** , 支 持 APP 和 微 服 務(wù) 無(wú) 狀 態(tài) 認(rèn) 證 ;
  • ** 用 OAuth2 實(shí) 現(xiàn) 第 三 方 登 錄 ** , 開(kāi) 啟 框 架 默 認(rèn) 安 全 防 護(hù) 。

? 小 明 的 最 終 感 悟 :
Spring Security 不 是 一 堆 復(fù) 雜 的 配 置 , 而 是 一 個(gè) “ 安 全 積 木 盒 ” 。 小 明 用 它 搭 建 了 攝 影 網(wǎng) 站 的 安 全 堡 壘 , 從 默 認(rèn) 配 置 到 自 定 義 擴(kuò) 展 , 從 Web 到 APP , 從 賬 號(hào) 密 碼 到 第 三 方 登 錄 , 每 一 步 都 踩 在 “ 需 求 ” 和 “ 技 術(shù) ” 的 結(jié) 合 點(diǎn) 上 。 現(xiàn) 在 , 他 可 以 專 心 拍 攝 更 美 的 照 片 , 而 網(wǎng) 站 的 安 全 , 交 給 Spring Security 就 夠 了 !

到此這篇關(guān)于Spring Security入門(mén)到深入實(shí)戰(zhàn)步驟詳解的文章就介紹到這了,更多相關(guān)Spring Security入門(mén)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

盐边县| 上犹县| 佛学| 千阳县| 泗洪县| 梁平县| 新竹市| 双柏县| 饶河县| 文登市| 屏东市| 景泰县| 天津市| 关岭| 化德县| 友谊县| 南丰县| 宁化县| 莎车县| 印江| 昌黎县| 莫力| 陵水| 迁西县| 堆龙德庆县| 平江县| 乡城县| 昌邑市| 荔浦县| 万源市| 麟游县| 霍邱县| 无极县| 壤塘县| 南通市| 长宁区| 通海县| 北海市| 黔西| 郧西县| 延庆县|