Spring 启动 OAuth2 手动创建新的 JWT 令牌
Spring Boot OAuth2 manually create new JWT token
在我的 Spring 启动应用程序中,我已经配置 Spring OAuth2 服务器和 JWT 令牌。
我还添加了 Spring 社交配置,以便能够通过各种社交网络(如 Twitter、Facebook 等)对用户进行身份验证。
这是我的 SpringSocial
配置:
@Configuration
@EnableSocial
public class SocialConfig extends SocialConfigurerAdapter {
@Bean
public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SimpleSignInAdapter(authTokenServices, "client_id", userService));
}
...
}
此外,根据民谣回答Integrate Spring Security OAuth2 and Spring Social,我已经实施SimpleSignInAdapter
以处理与第 3 方社交网络的成功身份验证:
public class SimpleSignInAdapter implements SignInAdapter {
final static Logger logger = LoggerFactory.getLogger(SimpleSignInAdapter.class);
public static final String REDIRECT_PATH_BASE = "/#/login";
public static final String FIELD_TOKEN = "access_token";
public static final String FIELD_EXPIRATION_SECS = "expires_in";
private final AuthorizationServerTokenServices authTokenServices;
private final String localClientId;
private final UserService userService;
public SimpleSignInAdapter(AuthorizationServerTokenServices authTokenServices, String localClientId, UserService userService){
this.authTokenServices = authTokenServices;
this.localClientId = localClientId;
this.userService = userService;
}
@Override
public String signIn(String userId, Connection<?> connection, NativeWebRequest request) {
UserDetails userDetails = loadUserById(Long.parseLong(userId));
OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(userDetails));
String redirectUrl = new StringBuilder(REDIRECT_PATH_BASE)
.append("?").append(FIELD_TOKEN).append("=")
.append(encode(oauth2Token.getValue()))
.append("&").append(FIELD_EXPIRATION_SECS).append("=")
.append(oauth2Token.getExpiresIn())
.toString();
return redirectUrl;
}
private OAuth2Authentication convertAuthentication(UserDetails userDetails) {
OAuth2Request request = new OAuth2Request(null, localClientId, null, true, null, null, null, null, null);
return new OAuth2Authentication(request, new UsernamePasswordAuthenticationToken(userDetails, "N/A", userDetails.getAuthorities()));
}
private String encode(String in) {
String res = in;
try {
res = UriUtils.encode(in, "UTF-8");
} catch(UnsupportedEncodingException e){
logger.error("ERROR: unsupported encoding: " + "UTF-8", e);
}
return res;
}
public UserDetails loadUserById(Long id) throws UsernameNotFoundException {
User user = userService.findUserById(id);
if (user == null) {
throw new UsernameNotFoundException("User " + id + " not found.");
}
Set<Permission> permissions = userService.getUserPermissions(user);
return new DBUserDetails(user, permissions);
}
}
除一件事外一切正常 - 以下代码行生成纯 OAuth2 访问令牌:
OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(userDetails));
但我需要创建 JWT 令牌。
如何创建此令牌或将其转换为基于 JWT 的令牌?我想我可以使用 JwtAccessTokenConverter
class 来达到这个目的,但现在不知道怎么做。
调试后找到解决办法:
private final TokenEnhancer tokenEnhancer;
...
OAuth2Authentication authentication = convertAuthentication(userDetails);
OAuth2AccessToken accessToken = authTokenServices.createAccessToken(authentication);
accessToken = tokenEnhancer.enhance(accessToken, authentication);
这对我有用,因为我想要我自己的自定义 JWT 令牌。
DefaultTokenServices service = new DefaultTokenServices();
service.setTokenStore(jwtAccessTokenConverter);
service.setTokenEnhancer(jwtAccessTokenConverter);
OAuth2AccessToken token = service.createAccessToken(authentication);
自动装配 jwtAccessTokenConverter
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;
在我的 Spring 启动应用程序中,我已经配置 Spring OAuth2 服务器和 JWT 令牌。
我还添加了 Spring 社交配置,以便能够通过各种社交网络(如 Twitter、Facebook 等)对用户进行身份验证。
这是我的 SpringSocial
配置:
@Configuration
@EnableSocial
public class SocialConfig extends SocialConfigurerAdapter {
@Bean
public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) {
return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SimpleSignInAdapter(authTokenServices, "client_id", userService));
}
...
}
此外,根据民谣回答Integrate Spring Security OAuth2 and Spring Social,我已经实施SimpleSignInAdapter
以处理与第 3 方社交网络的成功身份验证:
public class SimpleSignInAdapter implements SignInAdapter {
final static Logger logger = LoggerFactory.getLogger(SimpleSignInAdapter.class);
public static final String REDIRECT_PATH_BASE = "/#/login";
public static final String FIELD_TOKEN = "access_token";
public static final String FIELD_EXPIRATION_SECS = "expires_in";
private final AuthorizationServerTokenServices authTokenServices;
private final String localClientId;
private final UserService userService;
public SimpleSignInAdapter(AuthorizationServerTokenServices authTokenServices, String localClientId, UserService userService){
this.authTokenServices = authTokenServices;
this.localClientId = localClientId;
this.userService = userService;
}
@Override
public String signIn(String userId, Connection<?> connection, NativeWebRequest request) {
UserDetails userDetails = loadUserById(Long.parseLong(userId));
OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(userDetails));
String redirectUrl = new StringBuilder(REDIRECT_PATH_BASE)
.append("?").append(FIELD_TOKEN).append("=")
.append(encode(oauth2Token.getValue()))
.append("&").append(FIELD_EXPIRATION_SECS).append("=")
.append(oauth2Token.getExpiresIn())
.toString();
return redirectUrl;
}
private OAuth2Authentication convertAuthentication(UserDetails userDetails) {
OAuth2Request request = new OAuth2Request(null, localClientId, null, true, null, null, null, null, null);
return new OAuth2Authentication(request, new UsernamePasswordAuthenticationToken(userDetails, "N/A", userDetails.getAuthorities()));
}
private String encode(String in) {
String res = in;
try {
res = UriUtils.encode(in, "UTF-8");
} catch(UnsupportedEncodingException e){
logger.error("ERROR: unsupported encoding: " + "UTF-8", e);
}
return res;
}
public UserDetails loadUserById(Long id) throws UsernameNotFoundException {
User user = userService.findUserById(id);
if (user == null) {
throw new UsernameNotFoundException("User " + id + " not found.");
}
Set<Permission> permissions = userService.getUserPermissions(user);
return new DBUserDetails(user, permissions);
}
}
除一件事外一切正常 - 以下代码行生成纯 OAuth2 访问令牌:
OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(userDetails));
但我需要创建 JWT 令牌。
如何创建此令牌或将其转换为基于 JWT 的令牌?我想我可以使用 JwtAccessTokenConverter
class 来达到这个目的,但现在不知道怎么做。
调试后找到解决办法:
private final TokenEnhancer tokenEnhancer;
...
OAuth2Authentication authentication = convertAuthentication(userDetails);
OAuth2AccessToken accessToken = authTokenServices.createAccessToken(authentication);
accessToken = tokenEnhancer.enhance(accessToken, authentication);
这对我有用,因为我想要我自己的自定义 JWT 令牌。
DefaultTokenServices service = new DefaultTokenServices();
service.setTokenStore(jwtAccessTokenConverter);
service.setTokenEnhancer(jwtAccessTokenConverter);
OAuth2AccessToken token = service.createAccessToken(authentication);
自动装配 jwtAccessTokenConverter
@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;