spring cloud oauth2和spring security oauth2的区别
是 Spring Cloud 按照 OAuth2 的标准并结合 spring-security 封装好的一个具体实现。更多知识可以参考下面的文章
【权限----对比】深入理解Spring Cloud Security、OAuth2、JWT_Sunny3096的博客-CSDN博客_shiro和oauth2区别
spring-oauth父工程引用依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
spring-oauth2-client子工程
端口:8083
0、引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
</dependencies>
有需要注意的是:spring的版本不能高于spring-cloud,且spring-security-oauth2的2.0.2版本会报RedisConnection.set([B[B)V错误。
2、Config
(1)Oauth2Config
@Configuration
@EnableAuthorizationServer
public class Oauth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
public PasswordEncoder passwordEncoder;
@Autowired
public UserDetailsService myUserService;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenStore redisTokenStore;
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
security.tokenKeyAccess("isAuthenticated()");
//这个一定要开允许,否则/oauth/check_token会报403的错误
security.checkTokenAccess("permitAll()");
}
//配置在内存时存放的格式
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client_id")
.resourceIds("rid")
.secret(passwordEncoder.encode("secret"))
.authorizedGrantTypes("refresh_token", "authorization_code", "password")
.accessTokenValiditySeconds(3600)
.scopes("all");
}
//配置Userdetail的格式和redis
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.userDetailsService(myUserService)
.tokenStore(redisTokenStore);
}
}
注意:security.checkTokenAccess("permitAll()");这个一定要开允许,否则/oauth/check_token会报403的错误
(2)RedisTokenStoreConfig
注入redisTokenStore这个Bean,如果需要改redis存放token时的前缀,也可以在这个地方改
@Configuration
public class RedisTokenStoreConfig {
@Autowired
RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore(){
return new RedisTokenStore(redisConnectionFactory);
}
}
(3)WebSecurityConfig
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//重新注入password加密的Bean,采用BCry加密方法
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 允许所有匿名访问接口
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/oauth/**")
.authorizeRequests()
.antMatchers("/oauth/**").permitAll()
//解决跨域
.and().csrf().disable();
}
}
3、UserDetail改写
本Demo没有连接数据库,loadUserByUsername()方法中应该放入数据库的查询操作,本Demo固定写好账户
@Component(value = "myUserService")
public class MyUserService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("username:"+username);
if(!username.equals("admin")){
throw new UsernameNotFoundException("not found username");
}else{
String role="ADMIN";
ArrayList<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(role));
System.out.println("have add admin role");
String password=passwordEncoder.encode("123");
return new org.springframework.security.core.userdetails.User(username,password,authorities);
}
}
}
4、application.yml需要将redis配置好
其他服务子工程-调用Oauth2
端口:8084
0、application.yml 根据Oauth2的子工程填写
security:
oauth2:
client:
client-id: client_id
client-secret: secret
user-authorization-uri: http://localhost:8083/oauth/authorize
access-token-uri: http://localhost:8083/oauth/token
resource:
id: rid
user-info-uri: user-info
authorization:
check-token-access: http://localhost:8083/oauth/check_token
上图中的url都是调用Oauth2工程中的地址,注意端口
1、ResourceServerConfig资源服务器配置
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Value("${security.oauth2.client.client-id}")
private String clientId;
@Value("${security.oauth2.client.client-secret}")
private String secret;
@Value("${security.oauth2.authorization.check-token-access}")
private String checkTokenEndpointUrl;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean
public TokenStore redisTokenStore(){
return new RedisTokenStore(redisConnectionFactory);
}
public RemoteTokenServices tokenServices(){
RemoteTokenServices tokenServices = new RemoteTokenServices();
tokenServices.setClientId(clientId);
tokenServices.setClientSecret(secret);
tokenServices.setCheckTokenEndpointUrl(checkTokenEndpointUrl);
return tokenServices;
}
//配置资源服务器
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("rid")
.tokenServices(tokenServices());
}
}
2、Controller测试
@RestController
public class UserController {
@GetMapping("/get")
public Object get(Authentication authentication){
authentication.getCredentials();
OAuth2AuthenticationDetails details =(OAuth2AuthenticationDetails) authentication.getDetails();
String token = details.getTokenValue();
return token;
}
}
流程:1、启动oauth2客户端 2、启动子服务
POSTMAN调用
因为在Oauth2Config中配置了security.allowFormAuthenticationForClients();允许表单认证,所以可以在body的form中填入以下信息
结果:
将token填入另一个工程的Authorization中
结果:返回token成功