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

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

本示例提供了四大部分:

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

OAUTH2中的角色:

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

Grant Type:

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

1.基础环境

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

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 权限测试控制器

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

@RestController
public class DemoController {
 @GetMapping("/demo")
 @PreAuthorize("hasAuthority('query-demo')")
 public String getDemo(){
  return "good";
 }
}

4 api-gateway

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

  1. 本身作为一个client,使用implicit
  2. 作为外部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 客户端调用

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

admin用户

wyf用户

5.2 api-gateway中的webapp调用

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

6 源码地址

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • Spring Cloud下OAUTH2注销的实现示例
(0)

相关推荐

  • Spring Cloud下OAUTH2注销的实现示例

    接上文Spring Cloud下基于OAUTH2认证授权的实现,我们将基于Spring Cloud实现OAUTH2的注销功能. 1 增加自定义注销Endpoint 所谓注销只需将access_token和refresh_token失效即可,我们模仿org.springframework.security.oauth2.provider.endpoint.TokenEndpoint写一个使access_token和refresh_token失效的Endpoint: @FrameworkEndpoi

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

    在Spring Cloud需要使用OAUTH2来实现多个微服务的统一认证授权,通过向OAUTH服务发送某个类型的grant type进行集中认证和授权,从而获得access_token,而这个token是受其他微服务信任的,我们在后续的访问可以通过access_token来进行,从而实现了微服务的统一认证授权. 本示例提供了四大部分: discovery-service:服务注册和发现的基本模块 auth-server:OAUTH2认证授权中心 order-service:普通微服务,用来验证认

  • 浅谈Spring Cloud下微服务权限方案

    背景 从传统的单体应用转型Spring Cloud的朋友都在问我,Spring Cloud下的微服务权限怎么管?怎么设计比较合理?从大层面讲叫服务权限,往小处拆分,分别为三块:用户认证.用户权限.服务校验. 用户认证 传统的单体应用可能习惯了session的存在,而到了Spring cloud的微服务化后,session虽然可以采取分布式会话来解决,但终究不是上上策.开始有人推行Spring Cloud Security结合很好的OAuth2,后面为了优化OAuth 2中Access Token

  • 基于OAuth2.0授权系统的验证码功能的实现

    前言: 前一阵子,我自己一直在写一套后台管理系统<hanxiaozhang 后台管理系统>,后台技术栈基于SpringCloud组件实现的,授权则是使用的OAuth2.0.为了让系统的功能更加健全,我在系统内添加了验证码功能,具体实现如下: 正文: 我这套系统授权基于OAuth2.0实现,登录的是http://xxxx/oauth/token获取access_token.调用其他接口时,带上access_token进行权限认证.所以我要想加验证码,需要把验证码值放到http://xxxx/oa

  • Spring Cloud下实现用户鉴权的方案

    目录 一.整体架构 二.实现步骤 三.其它问题 四.完整代码 Java下常用的安全框架主要有Spring Security和shiro,都可提供非常强大的功能,但学习成本较高.在微服务下鉴权多多少少都会对服务有一定的入侵性. 为了降低依赖,减少入侵,让鉴权功能相对应用服务透明,我们采用网关拦截资源请求的方式进行鉴权. 一.整体架构 用户鉴权模块位于API GateWay服务中,所有的API资源请求都需要从此通过. 做身份认证,通过则缓存用户权限数据,不通过返回401 做用户鉴权,比对当前访问资源

  • Spring Security使用数据库登录认证授权

    目录 一.搭建项目环境 1.创建 RBAC五张表 2.创建项目 二.整合 Spring Security实现用户认证 1.后端整合 2.前端整合 三.整合 Spring Security实现用户授权 1.后端 2.前端 一.搭建项目环境 1.创建 RBAC五张表 RBAC,即基于角色的权限访问控制(Role-Based Access Control),就是用户通过角色与权限进行关联.在这种模型中,用户与角色之间,角色与权限之间,一般者是多对多的关系. 在 MySQL数据库中,创建如下几个表: D

  • Spring Cloud Alibaba 使用 Feign+Sentinel 完成熔断的示例

    Feign的使用 Feign也是网飞开发的,SpringCloud 使用 Feign 非常简单,我下边演示一下: 首先 服务消费者这边肯定需要一个对应的依赖: compile("org.springframework.cloud:spring-cloud-starter-openfeign") 需要启用Feign的话,也得在启动类上面加个注解 @EnableFeignClients 然后,创建一个 Feign 的接口,像这样子 package com.skypyb.sc.feign;

  • Spring Cloud Feign实现文件上传下载的示例代码

    目录 独立使用Feign 上传文件 下载文件 使用Spring Cloud Feign 上传文件 下载文件 总结 Feign框架对于文件上传消息体格式并没有做原生支持,需要集成模块feign-form来实现. 独立使用Feign 添加模块依赖: <!-- Feign框架核心 --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-core</arti

  • 详解Spring Cloud Gateway基于服务发现的默认路由规则

    1.Spring Gateway概述 1.1 什么是Spring Cloud Gateway Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式.Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代Netflix ZUUL,其不仅提供统一的路由

  • Springboot开发OAuth2认证授权与资源服务器操作

    设计并开发一个开放平台. 一.设计: 网关可以 与认证授权服务合在一起,也可以分开. 二.开发与实现: 用Oauth2技术对访问受保护的资源的客户端进行认证与授权. Oauth2技术应用的关键是: 1)服务器对OAuth2客户端进行认证与授权. 2)Token的发放. 3)通过access_token访问受OAuth2保护的资源. 选用的关键技术:Springboot, Spring-security, Spring-security-oauth2. 提供一个简化版,用户.token数据保存在内

随机推荐