为了实现JWT接口权限授予与校验功能,我们需要以下步骤:
1. 添加Spring Security和JWT依赖
Spring Security是一个现成的身份验证和授权框架,而JWT是一种安全性较高的身份认证方式。因此,我们需要添加相关依赖来支持这些功能。可以在Maven或Gradle中添加以下依赖:
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
...
</dependencies>
2. 实现UserDetailsService
如果我们要使用Spring Security来实现身份验证和授权,那么我们需要实现一个UserDetailsService接口来加载用户信息。可以通过实现loadUserByUsername方法来返回一个UserDetails对象,Spring Security将使用该对象进行身份验证。
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
// 从数据库或其他数据源加载用户信息
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found with username: " + username);
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
new ArrayList<>());
}
}
3. 实现JWT Token生成和校验
我们需要实现一个JWT Token工具类,用于生成和校验JWT Token。我们可以使用JJWT库来生成和解析JWT Token。
@Component
public class JwtTokenUtil {
private static final String SECRET_KEY = "secret";
public String generateToken(UserDetails userDetails) {
// 设置Token过期时间为10小时
long expirationTime = 36000000;
return Jwts.builder()
.setSubject(userDetails.getUsername())
.setExpiration(new Date(System.currentTimeMillis() + expirationTime))
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public boolean validateToken(String token, UserDetails userDetails) {
String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
private Boolean isTokenExpired(String token) {
final Date expiration = extractExpiration(token);
return expiration.before(new Date());
}
private Date extractExpiration(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getExpiration();
}
private String extractUsername(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody().getSubject();
}
}
4. 实现JWT过滤器
我们需要实现一个过滤器,用于在HTTP请求中解析JWT Token并在Spring Security中进行身份验证和授权。我们可以实现一个JwtRequestFilter类来处理此过程。
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtTokenUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
5. 配置Spring Security
我们需要配置Spring Security来允许对某些URL进行特殊的身份验证和授权。可以通过扩展WebSecurityConfigurerAdapter来实现此操作。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable()
.authorizeRequests().antMatchers("/authenticate").permitAll().
anyRequest().authenticated().and().
exceptionHandling().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
示例1
以下示例演示了如何在Spring Boot中使用JWT进行身份验证和授权。我们将获取JWT Token并在受保护的REST API上使用它来验证用户的身份。
@RestController
public class UserController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@PostMapping("/authenticate")
public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthenticationRequest authenticationRequest)
throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
authenticationRequest.getUsername(), authenticationRequest.getPassword()));
} catch (BadCredentialsException e) {
throw new Exception("Incorrect username or password", e);
}
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String jwt = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new AuthenticationResponse(jwt));
}
@GetMapping("/users")
public List<User> getUsers() {
return userService.findAll();
}
@PreAuthorize("hasRole('ADMIN')")
@PostMapping("/users")
public void addUser(@RequestBody User user) {
userService.save(user);
}
}
在上面的示例中,我们首先使用AuthenticationManager来进行身份验证。如果身份验证成功,将生成一个JWT Token并将其添加到响应中。
该代码还包括一个受保护的REST API,其中用户需要具有ADMIN角色才能访问。我们可以使用PreAuthorize注释来限制对此API的访问。在链式调用中使用了anyRequest().authenticated()来保护未受保护的REST端点,而permitAll()可用于允许所有用户获取JWT Token。
示例2
以下示例演示了如何在Spring Security中使用JWT进行授权和校验用户的身份。
@RestController
public class UserController {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@GetMapping("/users")
public List<User> getUsers(HttpServletRequest request) {
String authorizationHeader = request.getHeader("Authorization");
String jwtToken = authorizationHeader.substring(7);
JwtClaims jwtClaims = Jwts.parser().setSigningKey(JwtTokenUtil.SECRET_KEY).parseClaimsJws(jwtToken).getBody();
String username = jwtClaims.getSubject();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
return userService.findAll();
} else {
throw new UnauthorizedException("Invalid token");
}
}
}
在上面的示例中,我们从HTTP头中获取JWT Token,解析它并根据其内容加载用户信息。如果JWT Token是有效的,并且对当前请求的用户有授权,则我们可以执行请求。
我们还可以使用JwtTokenUtil来捕获JWToken并调用validateToken进行验证。如果验证成功,我们可以继续与请求。如果JWToken无效,则会抛出异常。
这里只是一个简单的示例,实际情况下可以根据需要进行更多的自定义授权和身份验证逻辑。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security代码实现JWT接口权限授予与校验功能 - Python技术站