学习笔记:微服务-9 spring cloud oauth2 server配置

spring cloud 对外服务的统一认证,以及各微服务之间相互调用的身份认证,需要有个认证服务器,上两节学习了以cas中央认证服务器作认证,作为spring cloud全家桶,本身提供了oauth2的统一认证,能很好地集成在整个微服务集群中,这节就学习oauth2服务器的搭建

1. 新建spring boot start project 我这设置项目名为:MicroserviceOauth2Server8301

2. pom.xml 加入以下依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</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>

3. application.properties 配置

server.port: 8301
spring.application.name=MicroserviceOauth2Server8301
spring.cloud.discovery.enabled=true
spring.redis.host= centos7.linbsoft.com
spring.redis.port=6379
eureka.client.serviceUrl.defaultZone=http://admin:123@centos7.linbsoft.com:8101/eureka/,http://admin:123@microservice1.linbsoft.com:8102/eureka/
logging.level.org.springframework.security=DEBUG

4. 启动类 MicroserviceOauth2Server8301Application

@EnableDiscoveryClient
@SpringBootApplication
public class MicroserviceOauth2Server8301Application {

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceOauth2Server8301Application.class, args);
    }
}

5.  授权服务配置类AuthorizationServerConfig,这里的登录客户是写死在内存的,实际部署可以通过数据库读取。


 
 
  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
  4. @Autowired
  5. private AuthenticationManager authenticationManager; // 认证管理器
  6. @Autowired
  7. private RedisConnectionFactory redisConnectionFactory; // redis连接工厂
  8. /**
  9. * 令牌存储
  10. * @return redis令牌存储对象
  11. */
  12. @Bean
  13. public TokenStore tokenStore() {
  14. return new RedisTokenStore(redisConnectionFactory);
  15. }
  16. @Override
  17. public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  18. endpoints.authenticationManager( this.authenticationManager);
  19. endpoints.tokenStore(tokenStore());
  20. }
  21. @Override
  22. public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
  23. security
  24. .tokenKeyAccess( "permitAll()")
  25. .checkTokenAccess( "isAuthenticated()");
  26. }
  27. @Override
  28. public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  29. clients.inMemory()
  30. .withClient( "admin")
  31. .scopes( "read")
  32. .secret( new BCryptPasswordEncoder().encode( "123456"))
  33. .authorizedGrantTypes( "password", "authorization_code", "refresh_token")
  34. .and()
  35. .withClient( "webapp")
  36. .scopes( "xx")
  37. .authorizedGrantTypes( "implicit");
  38. }
  39. }

6. 应用服务器网站本身的安全配置类SecurityConfig


 
 
  1. Configuration
  2. @EnableWebSecurity
  3. @EnableGlobalMethodSecurity(prePostEnabled = true)
  4. public class SecurityConfig extends WebSecurityConfigurerAdapter {
  5. @Bean
  6. public UserDetailsService userDetailsService() {
  7. return new CustomUserDetailsService();
  8. }
  9. @Bean
  10. public PasswordEncoder passwordEncoder() {
  11. // return PasswordEncoderFactories.createDelegatingPasswordEncoder();
  12. return new BCryptPasswordEncoder();
  13. }
  14. @Autowired
  15. public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
  16. // auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
  17. auth.userDetailsService(userDetailsService());
  18. }
  19. @Override
  20. @Bean
  21. public AuthenticationManager authenticationManagerBean() throws Exception {
  22. return super.authenticationManagerBean();
  23. }
  24. @Override
  25. protected void configure(HttpSecurity http) throws Exception {
  26. http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll().anyRequest().authenticated().and()
  27. .httpBasic().and().csrf().disable();
  28. }

7. oauth2本身也是一个资源服务器,配置类ResourceServerConfig


 
 
  1. @Configuration
  2. @EnableResourceServer
  3. public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  4. @Override
  5. public void configure(HttpSecurity http) throws Exception {
  6. http.requestMatcher( new OAuth2RequestedMatcher())
  7. .authorizeRequests()
  8. .antMatchers(HttpMethod.OPTIONS).permitAll()
  9. .anyRequest().authenticated();
  10. }
  11. private static class OAuth2RequestedMatcher implements RequestMatcher {
  12. @Override
  13. public boolean matches(HttpServletRequest request) {
  14. String auth = request.getHeader( "Authorization");
  15. boolean haveOauth2Token = (auth != null) && auth.startsWith( "Bearer");
  16. boolean haveAccessToken = request.getParameter( "access_token")!= null;
  17. return haveOauth2Token || haveAccessToken;
  18. }
  19. }
  20. }

8. 自定义用户服务类CustomUserDetailsService ,实例化方法  loadUserByUsername ,本方法的作用是根据登录用户名,查找获取用户类,包含用户账号,密码,权限等,这个一般需要查找数据库获取(与第5步的获取登录账号密码一致),这里demo就直接生成一个固定的用户测试。


 
 
  1. @Service
  2. public class CustomUserDetailsService implements UserDetailsService {
  3. @Override
  4. public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  5. System.out.println( "当前的用户名是:"+username);
  6. //这里为了方便测试,就直接返回一个用户信息,实际当中这里修改为查询数据库或者调用服务什么的来获取用户信息
  7. //根据登录名 到数据库取出用户信息
  8. User user = mockUser();
  9. return user;
  10. }
  11. // BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
  12. private User mockUser() {
  13. Collection<GrantedAuthority> authorities = new HashSet<>();
  14. authorities.add( new SimpleGrantedAuthority( "admin-role")); //用户所拥有的角色信息
  15. User user = new User( "admin", new BCryptPasswordEncoder().encode( "123456"),authorities);
  16. // User user = new User("admin","12345",authorities);
  17. return user;
  18. }
  19. }

9. 通过验证后,获取用户 map为 “/user”

@RestController
public class UserController {
@GetMapping("/user")
public Principal user(Principal user){
return user;
 }
}

10. 测试

首先可以通过Postman 测试api接口

以上是正常获取登录用户信息

也可以通过浏览器测试,输入账号密码后,即可看到保护的资源,这里是用户信息

 

测试流程:

1. 获取code

http://centos7.linbsoft.com:8301/oauth/authorize?response_type=code&client_id=admin&grant_type=code&redirect_uri=http://centos7.linbsoft.com:8301

弹出登录界面,登录后获取code

2. 获取token,post方法提交,把获取的code写入

http://centos7.linbsoft.com:8301/oauth/token?client_id=admin&grant_type=authorization_code&code=7hZ5jw&redirect_uri=http://centos7.linbsoft.com:8301

获取到token

{
    "access_token": "e86e7551-a01f-42af-830e-78f41c473bb8",
    "token_type": "bearer",
    "refresh_token": "647ddcaf-3416-47f7-8264-ebad1a374152",
    "expires_in": 42541,
    "scope": "read"
}

到redis查看到缓存的token

127.0.0.1:6379> keys *
 1) "uname_to_access:admin:admin"
 2) "auth:e86e7551-a01f-42af-830e-78f41c473bb8"
 3) "client_id_to_access:admin"
 4) "refresh:647ddcaf-3416-47f7-8264-ebad1a374152"
 5) "access:e86e7551-a01f-42af-830e-78f41c473bb8"
 6) "refresh_to_access:647ddcaf-3416-47f7-8264-ebad1a374152"
7) "refresh_auth:647ddcaf-3416-47f7-8264-ebad1a374152"
8) "access_to_refresh:e86e7551-a01f-42af-830e-78f41c473bb8"
9) "auth_to_access:35eb42947eaa87475ff2746ebe2a93f1"
 

3.用获取的token 访问资源

http://centos7.linbsoft.com:8301/user?access_token=e86e7551-a01f-42af-830e-78f41c473bb8

返回如下:

{"authorities":[{"authority":"admin-role"}],"details":{"remoteAddress":"192.168.49.141","sessionId":"724EE7828B6D43CD6D76C52101895155","tokenValue":"e86e7551-a01f-42af-830e-78f41c473bb8","tokenType":"Bearer","decodedDetails":null},"authenticated":true,"userAuthentication":{"authorities":[{"authority":"admin-role"}],"details":{"remoteAddress":"192.168.49.141","sessionId":null},"authenticated":true,"principal":{"password":null,"username":"admin","authorities":[{"authority":"admin-role"}],"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true,"enabled":true},"credentials":null,"name":"admin"},"oauth2Request":{"clientId":"admin","scope":["read"],"requestParameters":{"code":"WgI15s","grant_type":"authorization_code","response_type":"code","redirect_uri":"http://centos7.linbsoft.com:8301","client_id":"admin"},"resourceIds":[],"authorities":[],"approved":true,"refresh":false,"redirectUri":"http://centos7.linbsoft.com:8301","responseTypes":["code"],"extensions":{},"grantType":"authorization_code","refreshTokenRequest":null},"principal":{"password":null,"username":"admin","authorities":[{"authority":"admin-role"}],"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true,"enabled":true},"credentials":"","clientOnly":false,"name":"admin"}
 
 

本学习参考多位网友文章,在此不一一列出,谢谢。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值