Spring Cloud下基于OAUTH2认证授权的实现

Spring Cloud下基于OAUTH2认证授权的实现 博客分类: java spring

Spring Cloud需要使用OAUTH2来实现多个微服务的统一认证授权,通过向OAUTH服务发送某个类型的grant type进行集中认证和授权,从而获得access_token,而这个token是受其他微服务信任的,我们在后续的访问可以通过access_token来进行,从而实现了微服务的统一认证授权。

本示例提供了四大部分:

  • discovery-service:服务注册和发现的基本模块
  • auth-server:OAUTH2认证授权中心
  • order-service:普通微服务,用来验证认证和授权
  • api-gateway:边界网关(所有微服务都在它之后)

OAUTH2中的角色:

  • Resource Server:被授权访问的资源
  • Authotization Server:OAUTH2认证授权中心
  • Resource Owner: 用户
  • Client:使用API的客户端(如Android 、IOS、web app)

Grant Type:

  • Authorization Code:用在服务端应用之间
  • Implicit:用在移动app或者web app(这些app是在用户的设备上的,如在手机上调起微信来进行认证授权)
  • Resource Owner Password Credentials(password):应用直接都是受信任的(都是由一家公司开发的,本例子使用)
  • Client Credentials:用在应用API访问。

1.基础环境

使用Postgres作为账户存储,Redis作为Token存储,使用docker-compose在服务器上启动PostgresRedis

1Redis: 2 image: sameersbn/redis:latest 3 ports: 4 - "6379:6379" 5 volumes: 6 - /srv/docker/redis:/var/lib/redis:Z 7 restart: always 8 9PostgreSQL: 10 restart: always 11 image: sameersbn/postgresql:9.6-2 12 ports: 13 - "5432:5432" 14 environment: 15 - DEBUG=false 16 17 - DB_USER=wang 18 - DB_PASS=yunfei 19 - DB_NAME=order 20 volumes: 21 - /srv/docker/postgresql:/var/lib/postgresql:Z

2.auth-server

2.1 OAuth2服务配置

Redis用来存储token,服务重启后,无需重新获取token.

1@Configuration 2@EnableAuthorizationServer 3public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { 4 @Autowired 5 private AuthenticationManager authenticationManager; 6 @Autowired 7 private RedisConnectionFactory connectionFactory; 8 9 10 @Bean 11 public RedisTokenStore tokenStore() { 12 return new RedisTokenStore(connectionFactory); 13 } 14 15 16 @Override 17 public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 18 endpoints 19 .authenticationManager(authenticationManager) 20 .tokenStore(tokenStore()); 21 } 22 23 @Override 24 public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 25 security 26 .tokenKeyAccess("permitAll()") 27 .checkTokenAccess("isAuthenticated()"); 28 } 29 30 @Override 31 public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 32 clients.inMemory() 33 .withClient("android") 34 .scopes("xx") //此处的scopes是无用的,可以随意设置 35 .secret("android") 36 .authorizedGrantTypes("password", "authorization_code", "refresh_token") 37 .and() 38 .withClient("webapp") 39 .scopes("xx") 40 .authorizedGrantTypes("implicit"); 41 } 42} 43 44

2.2 Resource服务配置

auth-server提供user信息,所以auth-server也是一个Resource Server

1@Configuration 2@EnableResourceServer 3public class ResourceServerConfig extends ResourceServerConfigurerAdapter { 4 5 @Override 6 public void configure(HttpSecurity http) throws Exception { 7 http 8 .csrf().disable() 9 .exceptionHandling() 10 .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)) 11 .and() 12 .authorizeRequests() 13 .anyRequest().authenticated() 14 .and() 15 .httpBasic(); 16 } 17} 18 19 20 21@RestController 22public class UserController { 23 24 @GetMapping("/user") 25 public Principal user(Principal user){ 26 return user; 27 } 28} 29

2.3 安全配置

1@Configuration 2public class SecurityConfig extends WebSecurityConfigurerAdapter { 3 4 5 6 @Bean 7 public UserDetailsService userDetailsService(){ 8 return new DomainUserDetailsService(); 9 } 10 11 @Bean 12 public PasswordEncoder passwordEncoder() { 13 return new BCryptPasswordEncoder(); 14 } 15 16 @Override 17 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 18 auth 19 .userDetailsService(userDetailsService()) 20 .passwordEncoder(passwordEncoder()); 21 } 22 23 @Bean 24 public SecurityEvaluationContextExtension securityEvaluationContextExtension() { 25 return new SecurityEvaluationContextExtension(); 26 } 27 28 //不定义没有password grant_type 29 @Override 30 @Bean 31 public AuthenticationManager authenticationManagerBean() throws Exception { 32 return super.authenticationManagerBean(); 33 } 34 35 36 37}

2.4 权限设计

采用用户(SysUser) 角色(SysRole) 权限(SysAuthotity)设置,彼此之间的关系是多对多。通过DomainUserDetailsService 加载用户和权限。

2.5 配置

1spring: 2 profiles: 3 active: ${SPRING_PROFILES_ACTIVE:dev} 4 application: 5 name: auth-server 6 7 jpa: 8 open-in-view: true 9 database: POSTGRESQL 10 show-sql: true 11 hibernate: 12 ddl-auto: update 13 datasource: 14 platform: postgres 15 url: jdbc:postgresql://192.168.1.140:5432/auth 16 username: wang 17 password: yunfei 18 driver-class-name: org.postgresql.Driver 19 redis: 20 host: 192.168.1.140 21 22server: 23 port: 9999 24 25 26eureka: 27 client: 28 serviceUrl: 29 defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ 30 31 32 33logging.level.org.springframework.security: DEBUG 34 35logging.leve.org.springframework: DEBUG 36 37##很重要 38security: 39 oauth2: 40 resource: 41 filter-order: 3

2.6 测试数据

data.sql里初始化了两个用户admin->ROLE_ADMIN->query_demo,wyf->ROLE_USER

3.order-service

3.1 Resource服务配置

1@Configuration 2@EnableResourceServer 3public class ResourceServerConfig extends ResourceServerConfigurerAdapter{ 4 5 @Override 6 public void configure(HttpSecurity http) throws Exception { 7 http 8 .csrf().disable() 9 .exceptionHandling() 10 .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED)) 11 .and() 12 .authorizeRequests() 13 .anyRequest().authenticated() 14 .and() 15 .httpBasic(); 16 } 17} 18

3.2 用户信息配置

order-service是一个简单的微服务,使用auth-server进行认证授权,在它的配置文件指定用户信息在auth-server的地址即可:

1security: 2 oauth2: 3 resource: 4 id: order-service 5 user-info-uri: http://localhost:8080/uaa/user 6 prefer-token-info: false

3.3 权限测试控制器

具备authorityquery-demo的才能访问,即为admin用户

1@RestController 2public class DemoController { 3 @GetMapping("/demo") 4 @PreAuthorize("hasAuthority('query-demo')") 5 public String getDemo(){ 6 return "good"; 7 } 8} 9

4 api-gateway

api-gateway在本例中有2个作用:

  • 本身作为一个client,使用implicit

  • 作为外部app访问的方向代理

4.1 关闭csrf并开启Oauth2 client支持

1@Configuration 2@EnableOAuth2Sso 3public class SecurityConfig extends WebSecurityConfigurerAdapter{ 4 @Override 5 protected void configure(HttpSecurity http) throws Exception { 6 7 http.csrf().disable(); 8 9 } 10 11}

4.2 配置

1zuul: 2 routes: 3 uaa: 4 path: /uaa/** 5 sensitiveHeaders: 6 serviceId: auth-server 7 order: 8 path: /order/** 9 sensitiveHeaders: 10 serviceId: order-service 11 add-proxy-headers: true 12 13security: 14 oauth2: 15 client: 16 access-token-uri: http://localhost:8080/uaa/oauth/token 17 user-authorization-uri: http://localhost:8080/uaa/oauth/authorize 18 client-id: webapp 19 resource: 20 user-info-uri: http://localhost:8080/uaa/user 21 prefer-token-info: false

5 演示

5.1 客户端调用

使用Postmanhttp://localhost:8080/uaa/oauth/token发送请求获得access_token(admin用户的如7f9b54d4-fd25-4a2c-a848-ddf8f119230b)

  • admin用户




  • wyf用户



5.2 api-gateway中的webapp调用

暂时没有做测试,下次补充。

http://www.wisely.top/2017/06/14/spring-cloud-oauth2-zuul/

6 源码地址

https://github.com/wiselyman/uaa-zuul

oauth2 spring cloud zuul

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Spring Cloud OAuth2 微服务认证授权

OAuth2.0是用于授权的行业标准协议,它致力于简化客户端开发人员的工作,同时为Web应用、桌面应用、移动应用等各种客户端应用提供了特定的授权流程。本文讲解如何使用OAuth2协议来授权客户端应用访问SpringCloud微服务。微服务认证授权概述单点登录相比于单体应用,微服务应用需要在多个服务之间共享