我有一个spring MVC应用程序和一个远程OAuth2
授权服务器。应使用远程服务器登录Web和移动应用程序,并授权微服务。用于授权的OAuth2服务器工作,当我直接调用获取令牌的路径时,该请求会正确返回访问和刷新令牌。
Spring Boot中AuthorizationServerConfigurerAdapter
服务器应用程序上的Oauth2
类看起来像这样:
package com.mydomain.oauth2.configuration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenStore tokenStore;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure( AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("acme")
.secret("acmesecret")
.accessTokenValiditySeconds(3600)
.scopes("read", "write")
.redirectUris("http://localhost:8080/login")
.authorizedGrantTypes("password", "refresh_token")
.autoApprove(true)
.resourceIds("resource");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer configurer) throws Exception {
configurer.authenticationManager(authenticationManager);
configurer.userDetailsService(userDetailsService);
configurer.tokenStore(tokenStore);
}
}
我在Spring上编写的不是Spring Boot的Web应用程序的WebSecurityConfigurerAdapter
类看起来像这样:
package com.domain2.web.configurations;
import java.util.Arrays;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
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.oauth2.client.DefaultOAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
import org.springframework.security.oauth2.client.token.DefaultAccessTokenRequest;
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
@Configuration
@EnableWebSecurity
@EnableOAuth2Client
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
OAuth2ClientContext oauth2ClientContext;
@Autowired
DataSource dataSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login*", "/forgot-password*", "/signup**", "/signup/**", "/resources/**", "/403", "/storage/api/download/**", "/test/public/**").permitAll()
.antMatchers("/user**").anonymous()
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedPage("/403")
.and().exceptionHandling()
.and()
.logout()
.logoutUrl("j_spring_security_logout")
.logoutSuccessUrl("/login")
.deleteCookies("JSESSIONID")
.and()
.csrf().disable();
}
@Bean
protected OAuth2ProtectedResourceDetails resource() {
ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setAccessTokenUri("http://localhost:9000/oauth/token");
resource.setClientId("acme");
resource.setClientSecret("acmesecret");
resource.setGrantType("password");
resource.setScope(Arrays.asList("read", "write"));
return resource;
}
@Bean
public OAuth2RestTemplate restTemplate() {
ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider();
AccessTokenRequest atr = new DefaultAccessTokenRequest();
OAuth2RestTemplate template = new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));
template.setAccessTokenProvider(accessTokenProvider);
return template;
}
}
我的登录控制器:
@Autowired
private OAuth2RestOperations oaut2Template;
@RequestMapping(value="/login", method = RequestMethod.POST)
public String login(@RequestParam(value = "password") String password, @RequestParam(value = "username") String username){
oaut2Template.getOAuth2ClientContext().getAccessTokenRequest().set("username", username);
oaut2Template.getOAuth2ClientContext().getAccessTokenRequest().set("password", password);
System.out.println("Token *******: " + oaut2Template.getAccessToken().getValue());
return "dashboard";
}
我的问题是如何在登录控制器上将我的Web应用程序中的访问令牌和Principal用户存储起来。在登录控制器中获取的访问令牌是有效的,但我没有找到具有外部oaut2授权服务器的实现ResourceOwnerPasswordResourceDetails
的示例,我很长时间都无法做到这一点。我将不胜感激任何帮助