Java中的服务端点认证与授权:JWT与Spring Security OAuth2
大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨如何在Java应用中实现服务端点的认证与授权,重点关注JWT(JSON Web Token)和Spring Security OAuth2。我们将通过实际代码示例展示如何使用这两种技术来保护和管理API端点。
1. JWT(JSON Web Token)认证
1.1 引入依赖
首先,我们需要在pom.xml
中添加JWT的依赖:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
1.2 JWT工具类
接下来,我们创建一个JWT工具类,用于生成和解析JWT:
package cn.juwatech.example;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "your-secret-key";
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1 hour
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static Claims extractClaims(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
public static String getUsername(String token) {
return extractClaims(token).getSubject();
}
public static boolean isTokenExpired(String token) {
return extractClaims(token).getExpiration().before(new Date());
}
public static boolean validateToken(String token, String username) {
return (username.equals(getUsername(token)) && !isTokenExpired(token));
}
}
1.3 JWT过滤器
创建一个JWT过滤器来处理请求中的JWT:
package cn.juwatech.example;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && JwtUtil.validateToken(token, JwtUtil.getUsername(token))) {
Authentication auth = new JwtAuthenticationToken(JwtUtil.getUsername(token), null, null);
SecurityContextHolder.getContext().setAuthentication(auth);
}
filterChain.doFilter(request, response);
}
}
1.4 配置Spring Security
在SecurityConfig
中配置Spring Security以使用JWT过滤器:
package cn.juwatech.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
2. Spring Security OAuth2
2.1 引入依赖
添加Spring Security OAuth2的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
2.2 配置OAuth2资源服务器
在application.yml
中配置OAuth2资源服务器:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://your-auth-server.com/oauth2/default
2.3 配置Spring Security
配置Spring Security以使用OAuth2资源服务器:
package cn.juwatech.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
}
2.4 自定义JWT解析
如果需要自定义JWT解析逻辑,可以实现JwtAuthenticationConverter
:
package cn.juwatech.example;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
public class CustomJwtAuthenticationConverter extends JwtAuthenticationConverter {
@Override
protected Collection<SimpleGrantedAuthority> extractAuthorities(Jwt jwt) {
Map<String, ?> claims = jwt.getClaims();
// Extract roles from JWT claims
return Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
}
}
并在SecurityConfig
中注册自定义的JwtAuthenticationConverter
:
@Bean
public JwtAuthenticationConverter jwtAuthenticationConverter() {
CustomJwtAuthenticationConverter converter = new CustomJwtAuthenticationConverter();
return converter;
}
3. 结论
本文通过代码示例详细介绍了如何使用JWT和Spring Security OAuth2实现Java应用的服务端点认证与授权。JWT提供了灵活的令牌管理方案,而OAuth2则为资源服务器提供了标准化的安全保障。这两种技术可以根据应用的需求来选择和配置,以确保服务端点的安全性。
本文著作权归聚娃科技微赚淘客系统开发者团队,转载请注明出处!