在 Java 中实现 JWT(JSON Web Token)单点登录有多种方式,以下是其中一些常见的实现方式以及它们的步骤流程、依赖坐标和示例代码。
依赖坐标:
在你的项目的 Maven 或 Gradle 配置文件中添加以下依赖:
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.2</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.2</version>
<scope>runtime</scope>
</dependency>
Gradle:
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.2'
步骤流程:
WebSecurityConfigurerAdapter
的配置类,然后配置安全规则。示例代码:
Spring Security 配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/public/**").permitAll() // 允许公共访问的路径
.anyRequest().authenticated() // 其他请求需要认证
.and()
.formLogin()
.and()
.logout()
.and()
.csrf().disable();
}
}
JWT 工具类:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JwtUtil {
private static final String SECRET_KEY = "yourSecretKey";
private static final long EXPIRATION_TIME = 86400000; // 1 day in milliseconds
public static String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static boolean validateToken(String token, UserDetails userDetails) {
String username = extractUsername(token);
return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private static String extractUsername(String token) {
return extractClaims(token).getSubject();
}
private static boolean isTokenExpired(String token) {
Date expiration = extractClaims(token).getExpiration();
return expiration.before(new Date());
}
private static Claims extractClaims(String token) {
return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
}
}
这只是一个简单的示例,实际项目中还需要考虑异常处理、密码加密等方面的细节。
依赖坐标:
在你的项目的 Maven 或 Gradle 配置文件中添加以下依赖:
Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
Gradle:
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
步骤流程:
示例代码:
OAuth2 配置:
@Configuration
@EnableOAuth2Client
public class OAuth2Config {
@Bean
public OAuth2AuthorizedClientService authorizedClientService() {
return new InMemoryOAuth2AuthorizedClientService();
}
@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(
ClientRegistration.withRegistrationId("google")
.clientId("yourClientId")
.clientSecret("yourClientSecret")
.redirectUriTemplate("{baseUrl}/login/oauth2/code/{registrationId}")
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.userInfoUri("https://www.googleapis.com/oauth2/v3/userinfo")
.userNameAttributeName(IdTokenClaimNames.SUB)
.clientName("Google")
.build()
);
}
}
登录回调处理:
@Controller
public class OAuth2LoginController {
@GetMapping("/login/oauth2/code/google")
public String handleGoogleLogin(@AuthenticationPrincipal OAuth2User oauth2User) {
// 获取用户信息并生成 JWT
UserDetails userDetails = mapOAuth2UserToUserDetails(oauth2User);
String token = JwtUtil.generateToken(userDetails);
// 在此处可以根据业务逻辑重定向到主页或其他页面,并将 JWT 传递给客户端
return "redirect:/";
}
private UserDetails mapOAuth2UserToUserDetails(OAuth2User oauth2User) {
// 将 OAuth2User 转换为 UserDetails,你可能需要根据实际情况进行调整
// 返回 UserDetails 对象,用于生成 JWT
}
}
请注意,以上示例代码仅为概念性示例,实际项目中需要根据具体的业务需求进行适当的调整和扩展。
这些方式只是 JWT 单点登录的一部分实现方式,实际上还有其他库和框架可以用于实现类似的功能。选择合适的方式取决于你的项目需求、技术栈和团队经验。在实际开发中,还需考虑安全性、性能、异常处理等方面的细节。