SpringSecurity入门
文章目录
- SpringSecurity入门
- 一、引言
- 二、快速入门
- 1、环境搭建
- 1.1、添加依赖
- 1.2、创建启动类
- 1.3、创建Controller
- 2、Spring Security配置
- 2.1、配置SecurityConfig
- 三、深入理解
- 1、认证和授权
- 1.1、认证(Authentication)
- 1.2、授权(Authorization)
- 2、自定义认证
- 2.1、JWT认证
- 2.2、自定义认证过滤器
- 四、总结
SpringSecurity入门
一、引言
在Java Web后端开发中,安全是一个不可忽视的重要部分。Spring Security是一个功能强大且可高度定制的身份验证和访问控制框架,它集成了Spring生态,提供了认证(Authentication)和授权(Authorization)的功能。本文将带你走进Spring Security的世界,从基础入门到实际应用,帮助你掌握Spring Security的核心概念和使用方式。
二、快速入门
1、环境搭建
首先,我们需要搭建一个Spring Boot项目,并引入Spring Security依赖。
1.1、添加依赖
在pom.xml
中添加以下依赖:
<dependencies><!-- Spring Boot Web Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Security Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- Lombok for reducing boilerplate code --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>
1.2、创建启动类
创建一个Spring Boot启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SecurityApplication {public static void main(String[] args) {SpringApplication.run(SecurityApplication.class, args);}
}
1.3、创建Controller
创建一个简单的Controller来测试:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class HelloController {@GetMapping("/hello")public String hello() {return "Hello, Spring Security!";}
}
2、Spring Security配置
接下来,我们需要配置Spring Security。
2.1、配置SecurityConfig
创建一个配置类SecurityConfig
,继承自WebSecurityConfigurerAdapter
:
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll().and().logout().permitAll();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("user").password("{noop}password").roles("USER");}
}
在这个配置中,我们启用了Spring Security,并配置了所有的请求都需要认证。同时,我们定义了一个内存中的用户认证信息。
三、深入理解
1、认证和授权
Spring Security的核心在于认证和授权。
1.1、认证(Authentication)
认证是确认用户身份的过程。在Spring Security中,这通常是通过UserDetailsService
接口实现的,它允许我们从数据库或其他服务中加载用户的认证信息。
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;import java.util.Collections;@Service
public class CustomUserDetailsService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 模拟从数据库中获取用户信息if ("user".equals(username)) {return new User("user", "password", Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));}throw new UsernameNotFoundException("User not found");}
}
在上述代码中,我们创建了一个CustomUserDetailsService
类,它实现了UserDetailsService
接口。loadUserByUsername
方法用于根据用户名加载用户信息。如果用户存在,则创建一个UserDetails
对象并返回;如果用户不存在,则抛出UsernameNotFoundException
异常。
1.2、授权(Authorization)
授权是确定用户是否有权限执行特定操作的过程。Spring Security提供了多种方式来定义和检查权限,包括注解、表达式语言等。
使用注解进行权限控制:
import org.springframework.security.access.prepost.PreAuthorize;@RestController
public class SecureController {@PreAuthorize("hasAuthority('ROLE_ADMIN')")@GetMapping("/secure/admin")public String adminEndpoint() {return "Admin endpoint";}@PreAuthorize("hasAnyAuthority('ROLE_USER', 'ROLE_ADMIN')")@GetMapping("/secure/user")public String userEndpoint() {return "User endpoint";}
}
在上述代码中,我们使用了@PreAuthorize
注解来控制对/secure/admin
和/secure/user
两个端点的访问。hasAuthority
函数用于检查用户是否具有特定的权限。
2、自定义认证
在实际应用中,我们可能需要自定义认证逻辑,比如使用JWT。
2.1、JWT认证
创建一个JWT工具类,用于生成和解析JWT:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;public class JwtUtil {private String secretKey = "secret";public String generateToken(String username) {return Jwts.builder().setSubject(username).signWith(SignatureAlgorithm.HS512, secretKey).compact();}public String extractUsername(String token) {return extractClaim(token, Claims::getSubject);}public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {final Claims claims = extractAllClaims(token).getBody();return claimsResolver.apply(claims);}private Claims extractAllClaims(String token) {return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();}
}
在上述代码中,我们创建了一个JwtUtil
类,它提供了生成JWT和解析JWT的方法。generateToken
方法用于生成一个JWT,extractUsername
方法用于从JWT中提取用户名。
2.2、自定义认证过滤器
创建一个自定义认证过滤器,用于处理JWT认证:
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class JwtAuthenticationFilter extends OncePerRequestFilter {private final JwtUtil jwtUtil;public JwtAuthenticationFilter(JwtUtil jwtUtil) {this.jwtUtil = jwtUtil;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {String token = request.getHeader("Authorization");if (token != null && token.startsWith("Bearer ")) {String username = jwtUtil.extractUsername(token.substring(7));if (username != null) {UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());SecurityContextHolder.getContext().setAuthentication(authentication);}}filterChain.doFilter(request, response);}
}
在上述代码中,我们创建了一个JwtAuthenticationFilter
类,它继承自OncePerRequestFilter
。doFilterInternal
方法用于处理JWT认证。如果请求头中包含JWT,则从JWT中提取用户名,并创建一个UsernamePasswordAuthenticationToken
对象,将其设置到SecurityContextHolder
中。
四、总结
通过本文的介绍,你应该对Spring Security有了基本的了解。从快速入门到深入理解,再到自定义认证,Spring Security提供了强大的安全性支持,可以帮助我们构建安全的Web应用。希望本文能够帮助你快速上手Spring Security,并在你的项目中发挥作用。
版权声明:本博客内容为原创,转载请保留原文链接及作者信息。
参考文章:
- 秒懂SpringBoot之易懂的Spring Security教程
- Spring Security 入门教程