今天完成的事情:
oAuth2项目收尾
明天计划的事情:
解决报错
遇到的问题:
报错401,已解决
收获:
创建一个用户服务,这个服务是管理用户相关数据的。
逻辑 客户端 账户密码登录到认证中心,认证中心返回一个token给客户端;客户端拿着返回的token去访问用户服务,中间需要经过认证中心验证token,返回该用户信息,包括权限;然后访问服务的业务接口,返回数据
1.导入依赖:
<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>
2.配置文件:
spring:
application:
name: client-user
redis:
database: 2
host: 127.0.0.1
port: 6379
password: wsjKBK1594023884!
jedis:
pool:
max-active: 8
max-idle: 8
min-idle: 0
timeout: 100ms
server:
port: 6101
servlet:
context-path: /client-user
security:
oauth2:
client:
client-id: user-client
client-secret: user-secret-8888
resource:
id: user-client
user-info-uri: user-info
authorization:
# resource:
# jwt:
# key-value: dev
注:client-id、client-secret 要和认证服务中的配置一致,不然会出现找不到的情况,access-token-uri 是密码模式需要用到的获取 token 的接口。
user-authorization-uri 是授权码认证方式需要的
authorization.check-token-access 的作用是:当此服务端接收到来自客户端的请求后,需要拿着请求中的 token 到认证中心做 token 验证,就是请求的这个接口
3.资源服务配置
@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);
}
@Bean
public RemoteTokenServices tokenService() {
RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setClientId(clientId);
tokenService.setClientSecret(secret);
tokenService.setCheckTokenEndpointUrl(checkTokenEndpointUrl);
return tokenService;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenServices(tokenService());
}
注意:因为使用的是 redis 作为 token 的存储,所以需要特殊配置一下叫做 tokenService 的 Bean,通过这个 Bean 才能实现 token 的验证。
4.RESTful 接口
@Slf4j
@RestController
public class UserController {
@GetMapping(value = "get")
//@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@PreAuthorize("hasAnyRole('ROLE_ADMIN')")
public Object get(Authentication authentication){
//Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
authentication.getCredentials();
OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)authentication.getDetails();
String token = details.getTokenValue();
return token;
}
只有当访问用户具有 ROLE_ADMIN 权限时才能访问,否则返回 401 未授权。
通过 Authentication 参数或者 SecurityContextHolder.getContext().getAuthentication() 可以拿到授权信息进行查看
测试认证:
检查代码,已经开启服务了
还是报错,重新找解决方案,找到了下面这个:
使用grant_type=password获取access_token时可以不指定client_id和client_secret,就会报这个错误,消除这个错误的方式,就是不论grant_type的值是什么都需要在参数中指定client_id和client_secret
确实可以返回token,可是为什么需要携带client_id和client_secret呢?
client_id和client_secret是 用户服务客户端中的 id 和 密码,这个和认证中心设置的对应
认证中心的配置:
拿现在token去访问用户服务,根据接口的逻辑,会把 token 原样返回:
@GetMapping(value = "get")
//@PreAuthorize("hasAuthority('ROLE_ADMIN')")
@PreAuthorize("hasAnyRole('ROLE_ADMIN')")
public Object get(Authentication authentication){
//Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
authentication.getCredentials();
OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)authentication.getDetails();
String token = details.getTokenValue();
return token;
}
评论