我有一种情况,我想自己创建一个访问令牌(所以不通过通常的过程)。我想出了类似的东西:
@Inject
private DefaultTokenServices defaultTokenServices;
...
OAuth2Authentication auth = xxx;
OAuth2AccessToken token = defaultTokenServices.createAccessToken(auth);
唯一的问题是我不确定如何创建OAuth2Authentication(在我的代码中使用xxx的部分)。我有用户&客户信息,我知道我想授予此令牌的权限。
答案 0 :(得分:17)
在这里,您的使用案例可能会根据您使用的流程略有不同。这适用于密码授权流程。有一些自定义类,如令牌存储,令牌增强等。但这只是为了我们自己的需要而修改的弹簧类的扩展版本。
HashMap<String, String> authorizationParameters = new HashMap<String, String>();
authorizationParameters.put("scope", "read");
authorizationParameters.put("username", "mobile_client");
authorizationParameters.put("client_id", "mobile-client");
authorizationParameters.put("grant", "password");
DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(authorizationParameters);
authorizationRequest.setApproved(true);
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_UNTRUSTED_CLIENT"));
authorizationRequest.setAuthorities(authorities);
HashSet<String> resourceIds = new HashSet<String>();
resourceIds.add("mobile-public");
authorizationRequest.setResourceIds(resourceIds);
// Create principal and auth token
User userPrincipal = new User(user.getUserID(), "", true, true, true, true, authorities);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userPrincipal, null, authorities) ;
OAuth2Authentication authenticationRequest = new OAuth2Authentication(authorizationRequest, authenticationToken);
authenticationRequest.setAuthenticated(true);
CustomTokenStore tokenStore = new CustomTokenStore();
// Token Enhancer
CustomTokenEnhancer tokenEnhancer = new CustomTokenEnhancer(user.getUserID());
CustomTokenServices tokenServices = new CustomTokenServices();
tokenServices.setTokenEnhancer(tokenEnhancer);
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(tokenStore);
OAuth2AccessToken accessToken = tokenServices.createAccessTokenForUser(authenticationRequest, user);
答案 1 :(得分:12)
以下是使用TokenEndpoint接口(用于公开REST服务)生成令牌的方法:
@Inject
private TokenEndpoint tokenEndpoint;
public ResponseEntity<?> getToken(Principal principal) {
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("client_id", "appid");
parameters.put("client_secret", "myOAuthSecret");
parameters.put("grant_type", "password");
parameters.put("password", myUser.getPassword());
parameters.put("scope", "read write");
parameters.put("username", myUser.getLogin());
return tokenEndpoint.getAccessToken(principal, parameters);
}
答案 2 :(得分:5)
其他方式,要手动生成OAuth2 Accesss Token
,我们可以使用TokenService
的实例
@Autowired
private AuthorizationServerEndpointsConfiguration configuration;
@Override
public String generateOAuth2AccessToken(User user, List<Role> roles, List<String> scopes) {
Map<String, String> requestParameters = new HashMap<String, String>();
Map<String, Serializable> extensionProperties = new HashMap<String, Serializable>();
boolean approved = true;
Set<String> responseTypes = new HashSet<String>();
responseTypes.add("code");
// Authorities
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for(Role role: roles)
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
OAuth2Request oauth2Request = new OAuth2Request(requestParameters, "clientIdTest", authorities, approved, new HashSet<String>(scopes), new HashSet<String>(Arrays.asList("resourceIdTest")), null, responseTypes, extensionProperties);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), "N/A", authorities);
OAuth2Authentication auth = new OAuth2Authentication(oauth2Request, authenticationToken);
AuthorizationServerTokenServices tokenService = configuration.getEndpointsConfigurer().getTokenServices();
OAuth2AccessToken token = tokenService.createAccessToken(auth);
return token.getValue();
}
答案 3 :(得分:1)
这对我有用:
@Override public OAuth2AccessToken getToken(String username, String password) {
HashMap<String, String> parameters = new HashMap<String, String>();
parameters.put("client_id", clientid);
parameters.put("grant_type", "password");
parameters.put("password", username);
parameters.put("scope", scope);
parameters.put("username", password);
AuthorizationRequest authorizationRequest = defaultOAuth2RequestFactory.createAuthorizationRequest(parameters);
authorizationRequest.setApproved(true);
OAuth2Request oauth2Request = defaultOAuth2RequestFactory.createOAuth2Request(authorizationRequest);
// Create principal and auth token
final UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken(
username, password);
Authentication authentication = authenticationManager.authenticate(loginToken);
OAuth2Authentication authenticationRequest = new OAuth2Authentication(oauth2Request, authentication);
authenticationRequest.setAuthenticated(true);
OAuth2AccessToken accessToken = tokenServices.createAccessToken(authenticationRequest);
return accessToken;
}
在Oauth2Configuration中:
@Bean
DefaultOAuth2RequestFactory defaultOAuth2RequestFactory() {
return new DefaultOAuth2RequestFactory(clientDetailsService);
}
Oauth2Configuration的其余部分应如下文所示:
http://stytex.de/blog/2016/02/01/spring-cloud-security-with-oauth2/
答案 4 :(得分:1)
我的解决方案基于Mop So的答案,但不是使用:
print(X_sparse.shape)
print(X.shape)
我用过:
return tokenEndpoint.getAccessToken(principal, parameters);
为什么呢?因为如果您使用tokenEndpoint.postAccessToken(principal, parameters);
,则endpoing将为您提供tokenEndpoint.getAccessToken(principal, parameters)
,因为它尚未使用HttpRequestMethodNotSupportedException
方法调用。至少,这是我GET
spring-security-oauth2-2.0.13.RELEASE
答案 5 :(得分:0)
我在这里列出的所有实现都遇到了问题,所以我终于设法使用无状态服务器,oauth2和google social来实现自己的目标。这只是本教程的最后一部分,缺少here
对我来说,问题是执行google oauth之后,我需要将10秒持续时间的令牌交换为寿命长的令牌。为此,我需要生成一个JWT令牌并将其与我自己生成的真实访问令牌进行交换。
@Service
class SocialTokenVerificationService {
@Autowired
private lateinit var jwsTokenService: JWSTokenService
@Autowired
private lateinit var clientDetailsService: ClientDetailsService
@Autowired
private lateinit var userService: UserService
@Autowired
private lateinit var tokenServices: DefaultTokenServices
@Autowired
private lateinit var tokenRequestFactory: OAuth2RequestFactory
fun verifyToken(token: String): OAuth2AccessToken? {
val claimSet = jwsTokenService.parseToken(token)
val userDetails = userService.loadUserByUsername(claimSet.subject)
val client = clientDetailsService.loadClientByClientId(DEFAULT_SERVER_CLIENT)
val parameters = HashMap<String, String>()
val authentication = UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities)
return tokenServices.createAccessToken(OAuth2Authentication(
tokenRequestFactory.createOAuth2Request(client, TokenRequest(parameters, client.clientId, listOf("read", "write"), "password")),
authentication
))
}
}
JWSTokenService
:它是一个自我实现的类,用于对Google oauth和我的Google交换令牌进行编码和解码。 ClientDetailsService
:声明为授权服务器一部分的bean。来自我的数据库
覆盖有趣的configure(客户:ClientDetailsServiceConfigurer){ client.jdbc(数据源) }
UserService
:仅是扩展了UserDetailsService
的用户服务,以便从数据库中获取我的用户
DefaultTokenServices
:实现为如下所示的主bean
@Bean
@Primary
fun tokenServices(): DefaultTokenServices {
val defaultTokenServices = DefaultTokenServices()
defaultTokenServices.setTokenStore(tokenStore())
defaultTokenServices.setSupportRefreshToken(true)
defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter())
return defaultTokenServices
}
OAuth2RequestFactory
:实现为如下所示的Bean
@Bean
fun oauthRequestFactory(clientsDetails: ClientDetailsService): OAuth2RequestFactory {
return DefaultOAuth2RequestFactory(clientsDetails)
}
有了所有这些依赖性,我需要做的就是生成一个令牌,该令牌存储在数据库中并遵循与其他令牌相同的流程而不提供密码:
Authentication
类生成UsernamePasswordAuthenticationToken
。这是关键部分,调用DefaultTokenServices#createAccessToken
以获取新令牌。它需要一些参数来执行请求:
OAuth2Request
:可以使用OAuth2RequestFactory
Authentication
TokenRequest
。就我而言,我已经硬编码了因此,回顾一下如何手动创建令牌:
答案 6 :(得分:0)
在spring boot 2.2.2项目中,我正在使用以下代码来执行密码流服务器端:
我必须指定authorizedClientManager.setContextAttributesMapper
,因为PasswordOAuth2AuthorizedClientProvider
需要上下文中的特定属性。希望有帮助。
配置(application.yaml):
spring:
security:
oauth2:
client:
provider:
yourOauthProvider:
user-info-uri: ...
authorization-uri: ...
token-uri: ...
registration:
regId:
clientId: ...
clientSecret: ...
provider: yourOauthProvider
authorization-grant-type: password
redirect-uri-template: "{baseUrl}/login/oauth2/code/{registrationId}"
scope:
接线:
@Configuration
public class Oauth2ClientConfig {
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.password()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
authorizedClientManager.setContextAttributesMapper(r -> {
Map<String, Object> m = new HashMap<>();
m.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, r.getPrincipal().getPrincipal());
m.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, r.getPrincipal().getCredentials());
return m;
});
return authorizedClientManager;
}
}
服务:
class AuthService {
@Autowired
private OAuth2AuthorizedClientManager authorizedClientManager;
public OAuth2AccessToken authenticate(String user, String password) {
Authentication principal = new UsernamePasswordAuthenticationToken(
user,
password);
OAuth2AuthorizeRequest authorizeRequest =
OAuth2AuthorizeRequest.withClientRegistrationId("regId")
.principal(principal)
.build();
OAuth2AuthorizedClient authorizedClient =
this.authorizedClientManager.authorize(authorizeRequest);
return authorizedClient.getAccessToken();
}
}