发表于: 2021-05-17 23:24:33

1 1314


今天完成的事情:

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;
}








返回列表 返回列表
评论

    分享到