认证与授权:构建超级安全的 Spring Boot 应用,绝对不能缺少!

举报
bug菌 发表于 2025/02/26 10:30:38 2025/02/26
63 0 0
【摘要】 🏆本文收录于「滚雪球学SpringBoot」专栏,手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8 前言  你是否曾经想过,你的应用程序在开发过程中被用户访问的每一刻,背后隐藏着什么样...

🏆本文收录于「滚雪球学SpringBoot」专栏,手把手带你零基础入门Spring Boot,从入门到就业,助你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

  你是否曾经想过,你的应用程序在开发过程中被用户访问的每一刻,背后隐藏着什么样的风险呢?是的,作为开发者,你的责任就是要为用户提供一个安全且稳定的使用环境,确保他们的数据不会被恶意篡改或者泄露。为了做到这一点,**认证(Authentication)授权(Authorization)**是不可忽视的两个核心概念。

  你可能会想,认证和授权到底是什么?这两者有什么区别?别担心,在今天的文章里,我们将详细探讨如何通过 Spring BootSpring Security 来处理应用中的认证和授权。我们不仅会讲解基础的认证方式,还会深入到一些更高级的授权管理机制,确保你能够在实际项目中完美应对各种安全需求。

  好了,废话不多说,让我们一步步进入这个充满挑战和刺激的认证与授权世界吧!🎮

📚 目录

  1. 🔑 用户身份验证:基本认证、表单认证、OAuth2认证
  2. 🔒 授权管理与角色权限控制
  3. 🛠️ 使用 @PreAuthorize 与 @Secured 进行方法级安全
  4. 🪙 JWT(JSON Web Token)与 Spring Security 的集成

🔑 用户身份验证:基本认证、表单认证、OAuth2认证

  我们先从 认证 开始,这是一种验证用户身份的过程,只有通过认证,系统才会知道你是谁。一般来说,认证有几种方式:基本认证表单认证OAuth2认证。每种方式有各自的特点,可以根据实际需要选择不同的方式来实施。

1. 基本认证(Basic Authentication)

  所谓基本认证,就是通过 HTTP 请求头中的 Authorization 字段来传递用户名和密码的方式。简单、直接,但也有缺点:每次请求都需要发送用户名和密码,存在一定的安全隐患。虽然它在开发环境下还可以用,但在生产环境下,我们一般都会考虑用更加安全的方式。

如何配置基本认证?

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .httpBasic();  // 启用基本认证
    }
}

  这段代码非常简单,启用了基本认证,意味着任何请求都需要经过身份验证。简单吧?不过,正如前面所说,这种方式不太适合在生产环境中使用,尤其是当我们处理敏感数据时。

2. 表单认证(Form-based Authentication)

  表单认证通常是 Web 应用中最常见的认证方式。用户通过填写用户名和密码的表单来登录,提交后由后端验证。这个方式相比基本认证更加安全,因为用户名和密码不会直接出现在 HTTP 请求的头部,而是通过 POST 请求提交。

如何配置表单认证?

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/login", "/register").permitAll()  // 允许访问登录和注册页面
            .anyRequest().authenticated()  // 其他请求需要身份验证
            .and()
            .formLogin()  // 启用表单认证
            .loginPage("/login")  // 自定义登录页面
            .permitAll();  // 允许所有用户访问登录页面
    }
}

  通过这种方式,你不仅可以自定义登录页面,还能指定哪些路径允许匿名访问(比如登录和注册页面)。可以说,这种方式在大多数 Web 应用中都能派上用场。

3. OAuth2 认证:第三方登录的利器!

  OAuth2 是一个非常强大的认证协议,特别适合用于第三方登录。例如,用户可以通过 Google、Facebook 或 GitHub 等平台的账号登录你的应用,而不需要为你的应用创建一个新的用户名和密码。

如何配置 OAuth2 认证?

pom.xml 中添加 OAuth2 依赖:

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

然后在 application.yml 配置文件中添加 OAuth2 相关信息:

spring:
  security:
    oauth2:
      client:
        registration:
          google:
            client-id: YOUR_GOOGLE_CLIENT_ID
            client-secret: YOUR_GOOGLE_CLIENT_SECRET
            scope: profile, email
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
            authorization-grant-type: authorization_code
            client-name: Google

  这样一来,用户就可以通过 Google 账号登录你的应用。OAuth2 的最大优点是它不需要用户提供用户名和密码,降低了安全风险。用户只需授权一次,以后每次登录都会自动验证。


🔒 授权管理与角色权限控制

  授权 是在用户认证通过后,决定该用户能够访问哪些资源的过程。简单来说,就是授权决定了用户能做什么,而 认证 则确认了用户是谁。

1. 基于角色的权限控制

  在 Spring Security 中,通常是通过用户的角色来进行授权控制的。你可以通过配置 @PreAuthorize@Secured 注解,来控制哪些角色的用户可以访问哪些路径。

基于角色的权限控制配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")  // 只有 ADMIN 角色的用户可以访问 /admin 目录
            .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")  // 用户和管理员都可以访问 /user 目录
            .anyRequest().authenticated();
    }
}

  上面的代码展示了如何通过角色来控制权限:只有 ADMIN 角色的用户能访问 /admin 路径,而 USERADMIN 都可以访问 /user 路径。

2. 方法级安全控制:@PreAuthorize 和 @Secured

  在 Spring Security 中,我们还可以通过 @PreAuthorize@Secured 注解在方法级别进行更精细的权限控制。

示例:使用 @PreAuthorize

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long userId) {
    // 删除用户的操作
}

  这个方法会限制只有 ADMIN 角色的用户才能调用。非常适合需要细粒度控制的场景。

示例:使用 @Secured

@Secured("ROLE_USER")
public void viewProfile(Long userId) {
    // 查看用户资料的操作
}

  @Secured 注解比较简单,只能控制基于角色的权限,而 @PreAuthorize 允许你使用更复杂的表达式,比如根据用户的 ID 来控制访问权限。


🛠️ 使用 @PreAuthorize 与 @Secured 进行方法级安全

  在某些情况下,我们不仅需要基于 URL 的权限控制,还需要对具体的方法进行权限控制。这时候,@PreAuthorize@Secured 就派上了用场。

1. @PreAuthorize:支持复杂表达式

  @PreAuthorize 可以在方法执行之前,通过 SpEL(Spring Expression Language)进行权限判断。它比 @Secured 更加灵活,支持更复杂的逻辑。

示例:

@PreAuthorize("hasRole('ADMIN') or hasRole('MODERATOR')")
public void editPost(Long postId) {
    // 编辑帖子操作
}

  上面的方法可以被 ADMINMODERATOR 角色的用户调用。如果你有多个角色可以执行某个操作,@PreAuthorize 是一个非常好的选择。

2. @Secured:简单且易用

  相比 @PreAuthorize@Secured 更加简单,但它只支持基于角色的权限控制,不能使用复杂的表达式。

示例:

@Secured("ROLE_ADMIN")
public void deletePost(Long postId) {
    // 删除帖子操作
}

  这个方法只能被 ROLE_ADMIN 角色的用户访问。@Secured 是一种简洁的权限控制方式,适合一些简单的权限管理场景。


🪙 JWT(JSON Web Token)与 Spring Security 的集成

  在现代的 Web 应用中,使用 JWT(JSON Web Token) 来进行认证和授权已经成为一种趋势。与传统的基于 Session 的认证方式不同,JWT 采用无状态认证,这意味着每次请求都携带着认证信息,不需要服务器保存 Session。

1. JWT 的工作原理

JWT 通常由三部分组成:Header(头部)、Payload(负载)和 Signature(签名)。这些部分经过加密后合成一个字符串,通过 HTTP 请求头传递,后台可以通过这个 Token 来验证用户的身份。

2. 集成 JWT 与 Spring Security

  集成 JWT 的第一步是将 JWT 生成和验证的逻辑封装在工具类中,通常我们会使用 jjwt 库来处理 JWT。

pom.xml 中添加依赖:

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

然后,我们可以创建一个 JwtTokenUtil 类来生成和解析 JWT:

public class JwtTokenUtil {
    private static final String SECRET_KEY = "your-secret-key";

    public String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 86400000))  // 过期时间 24 小时
            .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
            .compact();
    }

    public String extractUsername(String token) {
        return Jwts.parser()
            .setSigningKey(SECRET_KEY)
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    }

    public boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }

    private Date extractExpiration(String token) {
        return Jwts.parser()
            .setSigningKey(SECRET_KEY)
            .parseClaimsJws(token)
            .getBody()
            .getExpiration();
    }
}

  接下来,我们需要创建一个过滤器,在每次请求中提取 JWT,并进行认证:

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = extractToken(request);
        if (token != null && jwtTokenUtil.isTokenExpired(token)) {
            Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            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;
    }
}

😎 总结

  经过这一篇文章的讲解,相信你已经对 Spring Boot 中的认证与授权有了更深入的理解。我们从最基本的身份验证方式出发,讲解了如何配置基本认证表单认证OAuth2 认证,并且介绍了如何通过 角色权限控制方法级安全JWT 集成来实现更加安全的应用。

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

  最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

  同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云多年度十佳博主/价值贡献奖,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。