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

SpringSecurity?鑒權(quán)與授權(quán)的具體使用

 更新時(shí)間:2025年07月01日 10:27:39   作者:超級(jí)小忍  
本文介紹了Spring?Security在前后端分離架構(gòu)中的核心應(yīng)用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

在現(xiàn)代 Web 開發(fā)中,前后端分離架構(gòu)已經(jīng)成為主流。后端專注于提供 RESTful API,而前端通過 AJAX 請(qǐng)求與后端交互。在這種架構(gòu)下,如何對(duì)用戶進(jìn)行 認(rèn)證(Authentication)授權(quán)(Authorization) 成為了系統(tǒng)設(shè)計(jì)中的核心問題。

Spring Security 是 Spring 框架中用于構(gòu)建安全系統(tǒng)的模塊,它不僅提供了強(qiáng)大的安全機(jī)制,還支持靈活的自定義配置。本文將圍繞 鑒權(quán)失敗和成功時(shí)的行為、需要攔截的路徑配置、以及具體的代碼實(shí)現(xiàn)方式 展開講解,并結(jié)合多個(gè)實(shí)際例子,幫助你深入理解 Spring Security 在前后端分離項(xiàng)目中的使用。

本文將從以下三個(gè)方面詳細(xì)展開:

  • 基礎(chǔ)概念:包括認(rèn)證、授權(quán)、關(guān)鍵組件及其作用;
  • 配置流程:從登錄請(qǐng)求到權(quán)限控制的完整流程;
  • 實(shí)戰(zhàn)示例:JWT 認(rèn)證、異常處理、多種路徑保護(hù)等具體實(shí)現(xiàn);

無論你是初學(xué)者還是有一定經(jīng)驗(yàn)的開發(fā)者,這篇文章都將為你提供一套完整的解決方案。

一、基礎(chǔ)概念詳解

Spring Security 的核心在于 認(rèn)證(Authentication)授權(quán)(Authorization)。

1.SecurityFilterChain(安全過濾器鏈)

  • 作用:定義 HTTP 請(qǐng)求的安全策略。
  • 位置:通常在配置類中通過 @Bean 注解創(chuàng)建。
  • 示例
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/public/**").permitAll()
            .anyRequest().authenticated()
        )
        .formLogin(withDefaults())
        .httpBasic(withDefaults());

    return http.build();
}

可以定義多個(gè) SecurityFilterChain 來處理不同路徑的權(quán)限策略。

2.UserDetailsService(用戶詳情服務(wù))

  • 作用:負(fù)責(zé)加載用戶信息(用戶名、密碼、權(quán)限)。
  • 實(shí)現(xiàn)方式
    • 內(nèi)存方式(適合測(cè)試):
@Bean
public UserDetailsService userDetailsService() {
    UserDetails user = User.withUsername("user")
                           .password(passwordEncoder().encode("123456"))
                           .roles("USER")
                           .build();
    return new InMemoryUserDetailsManager(user);
}
  • 數(shù)據(jù)庫方式(推薦生產(chǎn)環(huán)境):
@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("用戶不存在"));
        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_" + role.getName()))
                .collect(Collectors.toList());
    }
}

3.PasswordEncoder(密碼編碼器)

  • 作用:加密存儲(chǔ)密碼,并驗(yàn)證密碼是否匹配。
  • 常用實(shí)現(xiàn)
    • BCryptPasswordEncoder(推薦)
    • NoOpPasswordEncoder(不加密,僅用于開發(fā)階段)
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

4.JwtRequestFilter(自定義 JWT 過濾器)

  • 作用:攔截每個(gè)請(qǐng)求,解析 Token 并設(shè)置當(dāng)前用戶認(rèn)證信息。
  • 實(shí)現(xiàn)方式
@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException {

        String token = extractToken(request);

        if (token != null && jwtTokenUtil.validateToken(token)) {
            String username = jwtTokenUtil.getUsernameFromToken(token);
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);

            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }

        filterChain.doFilter(request, response);
    }

    private String extractToken(HttpServletRequest request) {
        String header = request.getHeader("Authorization");
        if (header != null && header.startsWith("Bearer ")) {
            return header.substring(7);
        }
        return null;
    }
}

5.AuthenticationEntryPoint(鑒權(quán)失敗處理器)

  • 作用:當(dāng)用戶未認(rèn)證訪問受保護(hù)資源時(shí)觸發(fā)該處理器。
  • 實(shí)現(xiàn)方式
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write("{\"error\": \"Unauthorized\", \"message\": \"認(rèn)證失敗,請(qǐng)重新登錄\"}");
    }
}

6.AccessDeniedHandler(權(quán)限不足處理器)

  • 作用:當(dāng)用戶已認(rèn)證但沒有訪問權(quán)限時(shí)觸發(fā)。
  • 實(shí)現(xiàn)方式
@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request,
                       HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.getWriter().write("{\"error\": \"Forbidden\", \"message\": \"你沒有權(quán)限訪問該資源\"}");
    }
}

二、配置流程詳解

成功時(shí)的流程:

  1. 用戶發(fā)送登錄請(qǐng)求 → /api/auth/login
  2. 后端驗(yàn)證用戶名密碼,生成 JWT Token 并返回給前端
  3. 前端保存 Token(如 localStorage)
  4. 后續(xù)請(qǐng)求攜帶 Token(放在 Header 中)
  5. 后端通過自定義 JWT 過濾器解析 Token 并設(shè)置認(rèn)證信息
  6. 用戶訪問受保護(hù)資源成功

失敗時(shí)的流程:

  1. Token 缺失或格式錯(cuò)誤 → 返回 401 Unauthorized
  2. Token 已過期或簽名無效 → 返回 401 Unauthorized
  3. 用戶沒有權(quán)限訪問某資源 → 返回 403 Forbidden

三、實(shí)戰(zhàn)示例詳解

示例 1:JWT Token 工具類(完整版)

@Component
public class JwtTokenUtil {

    private static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60; // 5小時(shí)
    private String secret = "your-secret-key-here";

    public String getUsernameFromToken(String token) {
        return getClaimFromToken(token, Claims::getSubject);
    }

    public Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token, Claims::getExpiration);
    }

    public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = getAllClaimsFromToken(token);
        return claimsResolver.apply(claims);
    }

    private Claims getAllClaimsFromToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(secret)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    private Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }

    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        return doGenerateToken(claims, userDetails.getUsername());
    }

    private String doGenerateToken(Map<String, Object> claims, String subject) {
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(subject)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    public Boolean validateToken(String token, UserDetails userDetails) {
        final String username = getUsernameFromToken(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
}

示例 2:登錄接口

@RestController
@RequestMapping("/api/auth")
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserDetailsService userDetailsService;

    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) throws Exception {
        try {
            authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
            );
        } catch (AuthenticationException e) {
            throw new Exception("用戶名或密碼錯(cuò)誤");
        }

        final UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsername());
        final String token = jwtTokenUtil.generateToken(userDetails);

        return ResponseEntity.ok().header("Authorization", "Bearer " + token).build();
    }
}

示例 3:多種路徑保護(hù)方式

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
        .csrf(AbstractHttpConfigurer::disable)
        .cors(cors -> cors.configurationSource(corsConfigurationSource()))
        .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
        .exceptionHandling(exceptions -> exceptions
            .authenticationEntryPoint(authenticationEntryPoint)
            .accessDeniedHandler(accessDeniedHandler))
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/api/public/**").permitAll()
            .requestMatchers("/api/admin/**").hasRole("ADMIN")
            .requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
            .anyRequest().authenticated()
        );

    return http.build();
}

結(jié)語

本文從 Spring Security 的基礎(chǔ)概念出發(fā),詳細(xì)介紹了認(rèn)證與授權(quán)的核心組件,并結(jié)合多個(gè)實(shí)戰(zhàn)示例展示了 JWT 的集成、路徑保護(hù)、異常處理等常見場(chǎng)景的實(shí)現(xiàn)方式。

到此這篇關(guān)于SpringSecurity 鑒權(quán)與授權(quán)的具體使用的文章就介紹到這了,更多相關(guān)SpringSecurity 鑒權(quán)與授權(quán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring?Boot實(shí)現(xiàn)熱部署的五種方式

    Spring?Boot實(shí)現(xiàn)熱部署的五種方式

    這篇文章主要介紹了Spring?Boot?五種熱部署方式,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • Java調(diào)用IK分詞器進(jìn)行分詞方式,封裝工具類

    Java調(diào)用IK分詞器進(jìn)行分詞方式,封裝工具類

    這篇文章主要介紹了Java調(diào)用IK分詞器進(jìn)行分詞方式,封裝工具類,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 給Java菜鳥的一些建議_關(guān)于Java知識(shí)點(diǎn)歸納(J2EE and Web 部分)

    給Java菜鳥的一些建議_關(guān)于Java知識(shí)點(diǎn)歸納(J2EE and Web 部分)

    下面小編就為大家?guī)硪黄oJava菜鳥的一些建議_關(guān)于Java知識(shí)點(diǎn)歸納(J2EE and Web 部分)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • 如何將char類型的數(shù)字字符轉(zhuǎn)換成int類型問題

    如何將char類型的數(shù)字字符轉(zhuǎn)換成int類型問題

    這篇文章主要介紹了如何將char類型的數(shù)字字符轉(zhuǎn)換成int類型問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • JGroups實(shí)現(xiàn)聊天小程序

    JGroups實(shí)現(xiàn)聊天小程序

    這篇文章主要為大家詳細(xì)介紹了JGroups實(shí)現(xiàn)聊天小程序,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • 分析設(shè)計(jì)模式之模板方法Java實(shí)現(xiàn)

    分析設(shè)計(jì)模式之模板方法Java實(shí)現(xiàn)

    所謂模板方法模式,就是一個(gè)對(duì)模板的應(yīng)用,就好比老師出試卷,每個(gè)人的試卷都是一樣的,這個(gè)原版試卷就是一個(gè)模板,可每個(gè)人寫在試卷上的答案都是不一樣的,這就是模板方法模式。它的主要用途在于將不變的行為從子類搬到超類,去除了子類中的重復(fù)代碼
    2021-06-06
  • Java+opencv3.2.0之直方圖均衡詳解

    Java+opencv3.2.0之直方圖均衡詳解

    這篇文章主要為大家詳細(xì)介紹了Java+opencv3.2.0之直方圖均衡的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 淺談MyBatis通用Mapper實(shí)現(xiàn)原理

    淺談MyBatis通用Mapper實(shí)現(xiàn)原理

    這篇文章主要介紹了淺談MyBatis通用Mapper實(shí)現(xiàn)原理,本文會(huì)先介紹通用 Mapper 的簡(jiǎn)單原理,然后使用最簡(jiǎn)單的代碼來實(shí)現(xiàn)這個(gè)過程。感興趣的小伙伴們可以參考一下
    2018-10-10
  • springboot集成screw反向生成數(shù)據(jù)庫說明文檔

    springboot集成screw反向生成數(shù)據(jù)庫說明文檔

    screw是一個(gè)一鍵式生成數(shù)據(jù)庫文檔的開源工具包,目前screw可以生成word、md和html格式類的文檔,本文主要來講講如何通過screw反向生成數(shù)據(jù)庫說明文檔,感興趣的可以了解下
    2025-01-01
  • java轉(zhuǎn)換字符串編碼格式的方法

    java轉(zhuǎn)換字符串編碼格式的方法

    這篇文章主要介紹了java轉(zhuǎn)換字符串編碼格式的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08

最新評(píng)論

郓城县| 静安区| 安西县| 舒城县| 中西区| 介休市| 石门县| 昭觉县| 新龙县| 神木县| 盈江县| 万全县| 井研县| 绿春县| 称多县| 庄河市| 辽阳县| 左权县| 甘德县| 壶关县| 托里县| 屯留县| 宜兰市| 板桥市| 宜良县| 遂溪县| 治县。| 佳木斯市| 乌拉特后旗| 中方县| 武胜县| 东明县| 彰武县| 修文县| 临清市| 平谷区| 贺州市| 三亚市| 无锡市| 安顺市| 正蓝旗|