我正在关注教程系列:https ://www.callicoder.com/spring-boot-security-oauth2-social-login-part-1/这是最好的教程,但令牌不存储在数据库和令牌中格式不适合我。
我需要一个 access_token 和 refresh_token,例如:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21pemVkIjoidHJ1ZSIsInVzZXJfbmFtZSI6ImRqb25pa2dhQGdtYWlsLmNvbSIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdLCJuYW1lIjoi0JXQstCz0LXQvdC40Lkg0JTQstC-0YDRhtC10LLQvtC5IiwiaWQiOjksImV4cCI6MTU1ODI1NTU1MCwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6Ijg1NjMxZmQ3LTRmNDMtNDIzNC05M2RlLTI5NTUxNDJjZmEzZiIsImNsaWVudF9pZCI6Imp3dENsaWVudElkUGFzc3dvcmQifQ.yP4dWiSdWPh1wsrirXzG6p19gjx5yI9MvsIjyESe1is",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjdXN0b21pemVkIjoidHJ1ZSIsInVzZXJfbmFtZSI6ImRqb25pa2dhQGdtYWlsLmNvbSIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdLCJhdGkiOiI4NTYzMWZkNy00ZjQzLTQyMzQtOTNkZS0yOTU1MTQyY2ZhM2YiLCJuYW1lIjoi0JXQstCz0LXQvdC40Lkg0JTQstC-0YDRhtC10LLQvtC5IiwiaWQiOjksImV4cCI6MTU2MDg0NjY1MCwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6Ijg4Y2FlNzYzLTJmOTItNDQ2Ni1hMmU3LTk0NGZmODQ4NmQ5NCIsImNsaWVudF9pZCI6Imp3dENsaWVudElkUGFzc3dvcmQifQ.0cUifDOtxAryTGD0qn2GHPtiAoNSlDfd3fpamlGGGrE",
"expires_in": 899,
"scope": "read write"
}
在使用 google、facebook 等社交帐户进行身份验证后,我通过手动创建令牌并重定向以获取一些带有令牌的数据,但令牌无效。
get - http://localhost:8080/user/me
bearer: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzb3VyY2VJZFRlc3QiXSwiY3VzdG9taXplZCI6InRydWUiLCJ1c2VyX25hbWUiOiJkam9uaWtnYUBnbWFpbC5jb20iLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXSwibmFtZSI6ItCV0LLQs9C10L3QuNC5INCU0LLQvtGA0YbQtdCy0L7QuSIsImlkIjo5LCJleHAiOjE1NTgyNTM3NTEsImF1dGhvcml0aWVzIjpbIlJPTEVfVVNFUiJdLCJqdGkiOiJhYzY0M2M2Yy0wZDYyLTQ2MDMtOWYxMy0wODE5MmNlYmYzZDAiLCJjbGllbnRfaWQiOiJqd3RDbGllbnRJZFBhc3N3b3JkIn0.d9_1gc_9PbrkG5mwoLRymBiPWpmH0VTcSEdnhz1aaxA
我收到回复
{
"error": "access_denied",
"error_description": "Invalid token does not contain resource id (jwtClientIdPassword)"
}
我有一个前端 - React,授权服务器 - Spring Security 5.0,postgres。我还使用 OAuth 2.0 和密码授予流程进行身份验证。令牌存储在数据库中。
我的授权适配器
@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}
@Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource.dataSource());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter()));
endpoints.authenticationManager(this.authenticationManager)
.tokenEnhancer(tokenEnhancerChain)
.tokenStore(tokenStore());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
CustomTokenConverter converter = new CustomTokenConverter();
converter.setSigningKey(signingKey);
return converter;
}
@Bean
@Primary
//Making this primary to avoid any accidental duplication with another token service instance of the same name
public DefaultTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter());
return defaultTokenServices;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
我的安全网络适配器
@Bean
public HttpCookieOAuth2AuthorizationRequestRepository cookieAuthorizationRequestRepository() {
return new HttpCookieOAuth2AuthorizationRequestRepository();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return DefaultPasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.exceptionHandling()
.authenticationEntryPoint(new RestAuthenticationEntryPoint())
.and()
.authorizeRequests()
.antMatchers("/auth/**", "/oauth2/**").permitAll()
.anyRequest()
.authenticated()
.and()
.oauth2Login()
.authorizationEndpoint().baseUri("/oauth2/authorize")
.authorizationRequestRepository(cookieAuthorizationRequestRepository())
.and()
.redirectionEndpoint().baseUri("/oauth2/callback/*")
.and()
.userInfoEndpoint()
.userService(customOAuth2UserService)
.and()
.successHandler(oAuth2AuthenticationSuccessHandler)
.failureHandler(oAuth2AuthenticationFailureHandler);
http.addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
在 oAuth2AuthenticationSuccessHandler.onAuthenticationSuccess 我尝试创建令牌
@Component
public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private TokenProvider tokenProvider;
private AppProperties appProperties;
private HttpCookieOAuth2AuthorizationRequestRepository httpCookieOAuth2AuthorizationRequestRepository;
=====
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
String targetUrl = determineTargetUrl(request, response, authentication);
if (response.isCommitted()) {
logger.debug("Response has already been committed. Unable to redirect to " + targetUrl);
return;
}
clearAuthenticationAttributes(request, response);
getRedirectStrategy().sendRedirect(request, response, targetUrl);
}
protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
Optional<String> redirectUri = CookieUtils.getCookie(request, REDIRECT_URI_PARAM_COOKIE_NAME)
.map(Cookie::getValue);
if(redirectUri.isPresent() && !isAuthorizedRedirectUri(redirectUri.get())) {
throw new BadRequestException("Sorry! We've got an Unauthorized Redirect URI and can't proceed with the authentication");
}
String targetUrl = redirectUri.orElse(getDefaultTargetUrl());
OAuth2AccessToken accessToken = tokenProvider.createAccessToken(authentication);
return UriComponentsBuilder.fromUriString(targetUrl)
.queryParam("token", accessToken.getValue())
.build().toUriString();
}
在这里我尝试创建 jwt 令牌
@Service
public class TokenProvider {
private static final Logger logger = LoggerFactory.getLogger(TokenProvider.class);
private AppProperties appProperties;
@Autowired
private TokenStore tokenStore;
@Autowired
private AuthorizationServerEndpointsConfiguration configuration;
public TokenProvider(AppProperties appProperties) {
this.appProperties = appProperties;
}
public OAuth2AccessToken createAccessToken(Authentication authentication) {
UserPrincipal user = (UserPrincipal)authentication.getPrincipal();
List<String> scopes = new ArrayList<>();
scopes.add("read");
scopes.add("write");
Map<String, String> requestParameters = new HashMap<String, String>();
Map<String, Serializable> extensionProperties = new HashMap<String, Serializable>();
requestParameters.put("client_id", "jwtClientIdPassword");
requestParameters.put("grant_type", "password");
requestParameters.put("scope", "read,write");
requestParameters.put("client_secret", "client");
requestParameters.put("username", user.getEmail());
requestParameters.put("password", user.getPassword());
boolean approved = true;
Set<String> responseTypes = new HashSet<String>();
responseTypes.add("code");
OAuth2Request oauth2Request = new OAuth2Request(requestParameters, "jwtClientIdPassword", user.getAuthorities(), approved, new HashSet<String>(scopes), new HashSet<String>(Arrays.asList("resourceIdTest")), null, responseTypes, extensionProperties);
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user, "N/A", user.getAuthorities());
OAuth2Authentication auth = new OAuth2Authentication(oauth2Request, authenticationToken);
AuthorizationServerTokenServices tokenService = configuration.getEndpointsConfigurer().getTokenServices();
OAuth2AccessToken token = tokenService.createAccessToken(auth);
return token;
}
我不确定我做得对。