Spring Cloud下基于OAUTH2认证授权的实现示例
在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
在服务器上启动postgres
和redis
。
redis: image: sameersbn/redis:latest ports: - "6379:6379" volumes: - /srv/docker/redis:/var/lib/redis:z restart: always postgresql: restart: always image: sameersbn/postgresql:9.6-2 ports: - "5432:5432" environment: - debug=false - db_user=wang - db_pass=yunfei - db_name=order volumes: - /srv/docker/postgresql:/var/lib/postgresql:z
2.auth-server
2.1 oauth2服务配置
redis
用来存储token
,服务重启后,无需重新获取token
.
@configuration @enableauthorizationserver public class authorizationserverconfig extends authorizationserverconfigureradapter { @autowired private authenticationmanager authenticationmanager; @autowired private redisconnectionfactory connectionfactory; @bean public redistokenstore tokenstore() { return new redistokenstore(connectionfactory); } @override public void configure(authorizationserverendpointsconfigurer endpoints) throws exception { endpoints .authenticationmanager(authenticationmanager) .tokenstore(tokenstore()); } @override public void configure(authorizationserversecurityconfigurer security) throws exception { security .tokenkeyaccess("permitall()") .checktokenaccess("isauthenticated()"); } @override public void configure(clientdetailsserviceconfigurer clients) throws exception { clients.inmemory() .withclient("android") .scopes("xx") //此处的scopes是无用的,可以随意设置 .secret("android") .authorizedgranttypes("password", "authorization_code", "refresh_token") .and() .withclient("webapp") .scopes("xx") .authorizedgranttypes("implicit"); } }
2.2 resource服务配置
auth-server
提供user信息,所以auth-server
也是一个resource server
@configuration @enableresourceserver public class resourceserverconfig extends resourceserverconfigureradapter { @override public void configure(httpsecurity http) throws exception { http .csrf().disable() .exceptionhandling() .authenticationentrypoint((request, response, authexception) -> response.senderror(httpservletresponse.sc_unauthorized)) .and() .authorizerequests() .anyrequest().authenticated() .and() .httpbasic(); } }
@restcontroller public class usercontroller { @getmapping("/user") public principal user(principal user){ return user; } }
2.3 安全配置
@configuration public class securityconfig extends websecurityconfigureradapter { @bean public userdetailsservice userdetailsservice(){ return new domainuserdetailsservice(); } @bean public passwordencoder passwordencoder() { return new bcryptpasswordencoder(); } @override protected void configure(authenticationmanagerbuilder auth) throws exception { auth .userdetailsservice(userdetailsservice()) .passwordencoder(passwordencoder()); } @bean public securityevaluationcontextextension securityevaluationcontextextension() { return new securityevaluationcontextextension(); } //不定义没有password grant_type @override @bean public authenticationmanager authenticationmanagerbean() throws exception { return super.authenticationmanagerbean(); } }
2.4 权限设计
采用用户(sysuser)
角色(sysrole)
权限(sysauthotity)
设置,彼此之间的关系是多对多
。通过domainuserdetailsservice
加载用户和权限。
2.5 配置
spring: profiles: active: ${spring_profiles_active:dev} application: name: auth-server jpa: open-in-view: true database: postgresql show-sql: true hibernate: ddl-auto: update datasource: platform: postgres url: jdbc:postgresql://192.168.1.140:5432/auth username: wang password: yunfei driver-class-name: org.postgresql.driver redis: host: 192.168.1.140 server: port: 9999 eureka: client: serviceurl: defaultzone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/ logging.level.org.springframework.security: debug logging.leve.org.springframework: debug ##很重要 security: oauth2: resource: filter-order: 3
2.6 测试数据
data.sql
里初始化了两个用户admin
->role_admin
->query_demo
,wyf
->role_user
3.order-service
3.1 resource服务配置
@configuration @enableresourceserver public class resourceserverconfig extends resourceserverconfigureradapter{ @override public void configure(httpsecurity http) throws exception { http .csrf().disable() .exceptionhandling() .authenticationentrypoint((request, response, authexception) -> response.senderror(httpservletresponse.sc_unauthorized)) .and() .authorizerequests() .anyrequest().authenticated() .and() .httpbasic(); } }
3.2 用户信息配置
order-service
是一个简单的微服务,使用auth-server
进行认证授权,在它的配置文件指定用户信息在auth-server
的地址即可:
security: oauth2: resource: id: order-service user-info-uri: http://localhost:8080/uaa/user prefer-token-info: false
3.3 权限测试控制器
具备authority
未query-demo
的才能访问,即为admin
用户
@restcontroller public class democontroller { @getmapping("/demo") @preauthorize("hasauthority('query-demo')") public string getdemo(){ return "good"; } }
4 api-gateway
api-gateway
在本例中有2个作用:
- 本身作为一个client,使用
implicit
- 作为外部app访问的方向代理
4.1 关闭csrf并开启oauth2 client支持
@configuration @enableoauth2sso public class securityconfig extends websecurityconfigureradapter{ @override protected void configure(httpsecurity http) throws exception { http.csrf().disable(); } }
4.2 配置
zuul: routes: uaa: path: /uaa/** sensitiveheaders: serviceid: auth-server order: path: /order/** sensitiveheaders: serviceid: order-service add-proxy-headers: true security: oauth2: client: access-token-uri: http://localhost:8080/uaa/oauth/token user-authorization-uri: http://localhost:8080/uaa/oauth/authorize client-id: webapp resource: user-info-uri: http://localhost:8080/uaa/user prefer-token-info: false
5 演示
5.1 客户端调用
使用postman
向http://localhost:8080/uaa/oauth/token
发送请求获得access_token
(admin用户的如7f9b54d4-fd25-4a2c-a848-ddf8f119230b
)
admin用户
wyf用户
5.2 api-gateway中的webapp调用
暂时没有做测试,下次补充。
6 源码地址
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
-
基于Spring Security的Oauth2授权实现方法
-
Spring Cloud下基于OAUTH2认证授权的实现示例
-
Spring Cloud实战 | 最终篇:Spring Cloud Gateway+Spring Security OAuth2集成统一认证授权平台下实现注销使JWT失效方案
-
Spring Cloud下基于OAUTH2认证授权(二)
-
Spring Cloud下基于OAUTH2认证授权(四)
-
基于Spring Security的Oauth2授权实现方法
-
Spring Cloud下基于OAUTH2认证授权的实现示例
-
Spring Cloud下OAUTH2注销的实现示例
-
Spring Cloud下OAUTH2注销的实现
-
Spring Cloud下OAUTH2注销的实现