介绍
在开发 web 应用程序时,安全权限控制是非常重要的一项功能。使用 Spring Boot、Spring Security 和 JWT(JSON Web Token)可以帮助我们实现简单且强大的 RESTful API 权限控制。
环境准备
首先,确保你的开发环境配置好了以下组件:
- JDK 1.8 或以上版本
- Maven 3.x 或以上版本
创建 Spring Boot 项目
使用 Maven 创建一个新的 Spring Boot 项目,执行以下命令:
mvn archetype:generate -DgroupId=com.example -DartifactId=spring-boot-security-jwt-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
添加依赖
在项目的 pom.xml
文件中添加以下依赖:
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.11.2</version>
</dependency>
</dependencies>
配置 Spring Security
在 Spring Boot 项目的 application.properties
文件中添加以下配置:
# 禁用 security 默认的 http basic 认证方式
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
然后,创建一个 SecurityConfig
类,配置 Spring Security:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/api/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
上面的配置禁用了 Spring Security 的默认 http basic 认证方式,并指定了登录接口 /api/authenticate
不需要认证即可访问。
定义用户服务
创建一个 UserService
接口,并实现 UserDetailsService
:
@Service
public class UserService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username);
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());
}
}
定义数据模型
创建一个 User
实体类来表示用户对象,并创建一个 UserRepository
接口继承自 JpaRepository
:
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
// getters and setters
}
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
实现认证和授权过滤器
创建一个 JwtAuthenticationFilter
类来处理认证逻辑:
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
setFilterProcessesUrl("/api/authenticate");
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
String token = Jwts.builder()
.setSubject(((User) authResult.getPrincipal()).getUsername())
.claim("authorities", new ArrayList<>())
.setExpiration(new Date(System.currentTimeMillis() + 864000000))
.signWith(SignatureAlgorithm.HS512, "SecretKeyToGenJWTs".getBytes())
.compact();
response.addHeader("Authorization", "Bearer " + token);
}
}
创建一个 JwtAuthorizationFilter
类来处理授权逻辑:
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String header = request.getHeader("Authorization");
if (header == null || !header.startsWith("Bearer ")) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader("Authorization");
if (token != null) {
String user = Jwts.parser()
.setSigningKey("SecretKeyToGenJWTs".getBytes())
.parseClaimsJws(token.replace("Bearer ", ""))
.getBody()
.getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
创建 RESTful API
创建一个 UserController
类来处理用户相关的 API:
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public List<User> getAllUsers() {
// 获取所有用户的逻辑
}
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
// 根据用户 ID 获取用户的逻辑
}
@PostMapping
public User createUser(@RequestBody User user) {
// 创建用户的逻辑
}
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
// 更新用户的逻辑
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
// 删除用户的逻辑
}
}
运行项目
运行项目并访问相应的 API 接口,例如:
curl -X GET http://localhost:8080/api/users
你可以使用 Postman 或其他工具来测试各个接口。
结束语
通过使用 Spring Boot、Spring Security 和 JWT,我们实现了简单且强大的 RESTful API 权限控制。这样的安全机制可以保护我们的应用程序,确保只有经过授权的用户才能访问敏感资源。
希望这篇博客对你了解 Spring Boot + Spring Security + JWT 的实际应用有所帮助,加油!
本文来自极简博客,作者:梦境旅人,转载请注明原文链接:Spring Boot Spring Security JWT 实现简单的 RESTful API 权限控制