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

Stella981
• 阅读 832

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

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个作用:

  • 本身作为一个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 客户端调用

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

  • admin用户

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


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


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


  • wyf用户

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


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


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

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
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
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
凯文86 凯文86
3年前
Spring Cloud OAuth2 微服务认证授权
OAuth2.0是用于授权的行业标准协议,它致力于简化客户端开发人员的工作,同时为Web应用、桌面应用、移动应用等各种客户端应用提供了特定的授权流程。本文讲解如何使用OAuth2协议来授权客户端应用访问SpringCloud微服务。微服务认证授权概述单点登录相比于单体应用,微服务应用需要在多个服务之间共享
Stella981 Stella981
3年前
Spring Boot 的 oAuth2 认证(附源码)
OAuth2统一认证原理OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorizationlayer)。"客户端"不能直接登录"服务提供商",只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围
Easter79 Easter79
3年前
SpringSecurity进阶:OAuth2.0详解
OAuth2是什么?OAuth是一个为了方便用户登入而使用的授权流程,他的优点是不需要向第三方平台暴露我们的用户名和密码,而是使用授权服务器颁发短期的token和效验token的方式开放部分资源给第三方平台OAuth是一个授权协议不是认证协议OAuth2的授权方式!(https://p1tt
Easter79 Easter79
3年前
SpringCloud(9)使用Spring Cloud OAuth2保护微服务系统
一、简介OAth2是一个标准的授权协议。在认证与授权的过程中,主要包含以下3种角色。服务提供方AuthorizationServer。资源持有者ResourceServer。客户端Client。OAuth2的认证流程如图所示,具体如下。!(https://o
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这