认证与授权:构建超级安全的 Spring Boot 应用,绝对不能缺少!
【摘要】 🏆本文收录于「滚雪球学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 Boot 和 Spring Security 来处理应用中的认证和授权。我们不仅会讲解基础的认证方式,还会深入到一些更高级的授权管理机制,确保你能够在实际项目中完美应对各种安全需求。
好了,废话不多说,让我们一步步进入这个充满挑战和刺激的认证与授权世界吧!🎮
📚 目录
- 🔑 用户身份验证:基本认证、表单认证、OAuth2认证
- 🔒 授权管理与角色权限控制
- 🛠️ 使用 @PreAuthorize 与 @Secured 进行方法级安全
- 🪙 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
路径,而 USER
和 ADMIN
都可以访问 /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) {
// 编辑帖子操作
}
上面的方法可以被 ADMIN
或 MODERATOR
角色的用户调用。如果你有多个角色可以执行某个操作,@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)