Coder Social home page Coder Social logo

uaa-zuul's Introduction

我的新书《从企业级开发到云原生微服务:Spring Boot 实战》即将出版,内容涵盖了丰富Spring Boot开发的相关知识,主要包含目录有:

  • 第一章 初识Spring Boot(快速领略Spring Boot的美丽)
  • 第二章 开发必备工具(对常用开发工具进行介绍:包含IntelliJ IDEA、Gradle、Lombok、Docker等)
  • 第三章 函数式编程
  • 第四章 Spring 5.x基础(以Spring 5.2.x为基础)
  • 第五章 深入Spring Boot(以Spring Boot 2.2.x为基础)
  • 第六章 Spring Web MVC
  • 第七章 数据访问(包含Spring Data JPA、Spring Data Elasticsearch和数据缓存)
  • 第八章 安全控制(包含Spring Security和OAuth2)
  • 第九章 响应式编程(包含Project Reactor、Spring WebFlux、Reactive NoSQL、R2DBC、Reactive Spring Security)
  • 第十章 事件驱动(包含JMS、RabbitMQ、Kafka、Websocket、RSocket)
  • 第11章 系统集成和批处理(包含Spring Integration和Spring Batch)
  • 第12章 Spring Cloud与微服务
  • 第13章 Kubernetes与微服务(包含Kubernetes、Helm、Jenkins、Istio) 多谢大家支持。

京东购买地址:https://item.jd.com/12760084.html

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:
  • password:
  • refrsh_token:

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)
                .userDetailsService(userDetailsService)//若无,refresh_token会有UserDetailsService is required错误
                .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

4.3 服务之间互调

feign client没有将access token放入请求头里,需定义一个OAuth2FeignRequestInterceptor的bean:

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 注销oauth2

6.1 增加自定义注销Endpoint

所谓注销只需将access_tokenrefresh_token失效即可,我们模仿org.springframework.security.oauth2.provider.endpoint.TokenEndpoint写一个使access_tokenrefresh_token失效的Endpoint:

@FrameworkEndpoint
public class RevokeTokenEndpoint {

    @Autowired
    @Qualifier("consumerTokenServices")
    ConsumerTokenServices consumerTokenServices;

    @RequestMapping(method = RequestMethod.DELETE, value = "/oauth/token")
    @ResponseBody
    public String revokeToken(String access_token) {
        if (consumerTokenServices.revokeToken(access_token)){
            return "注销成功";
        }else{
            return "注销失败";
        }
    }
}

6.2 注销请求方式

uaa-zuul's People

Contributors

wiselyman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

uaa-zuul's Issues

AuthorizationServerConfig 编译不过

@Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)//若无,refresh_token会有UserDetailsService is required错误
                .tokenStore(tokenStore());
    }

userDetailsService 在哪儿定义的呢

关于sso有点问题想请教下。

项目需要提供多终端支持使用,例如PC、Ipad、app等。在zuul多实例的情况下,如何share authenticationConctext?官方使用的是在zuul上实现spring-session,但是感觉这样并不是很好。而并且作者说@EnableOAuth2Sso不太适合面对多终端的情况,请问有什么好的建议处理吗?

关于注销的问题

我发现注销有时候可以注销,有时候不能注销
@controller
public class UserController {
@RequestMapping(value = "/user", produces = "application/json")
@responsebody
public Principal user(Principal user){
return user;
}

@Autowired
@Qualifier("consumerTokenServices")
ConsumerTokenServices consumerTokenServices;

@RequestMapping(value = "/loginOut")
@ResponseBody
public String revokeToken(String access_token) {
    try {
        if (consumerTokenServices.revokeToken(access_token)) {
            return "注销成功";
        } else {
            return "注销失败";
        }
    } catch (Exception e) {
        e.printStackTrace();
        return "异常";
    }

}

}
发现这样写就可以实现注销了,当然写个 .antMatchers("/loginOut").permitAll()

能不能在zuul上集成ResourceServer统一控制权限

大神请教一下。这个uaa-zuul的demo是在每个普通微服务上建立ResourceServer来保护api的。 这样子每次创建一个新的微服务都要配置一个ResourceServer的配置,略显的麻烦了。 我想在Zuul网关上统一创建一个ResourceServer来实现权限管理, 然后自个儿实现了一下,在zuul服务中 把SecurityConfig的configure(http)方法里面的http参数这么设置,http.authorizeRequests().antMatchers("/order/user").permitAll().anyRequest().authenticated();
然后通过链接发送http://localhost:xxxx/order/user,结果这个链接并没有被放行,还是需要获取token来得到Authentication 对象,并且在tokenService中找不到对应这个token的Authentication(此时我已经把token以Breaer类型写入到请求头中了,并且在application.yml中配置了auth服务获取userinfo的地址了),这个问题研究了好久了, 一直没有得到解决,

password模式登录问题

导入成功了,各个模块都可以正常启动,但是password模式下登录老是提示401?是需要修改哪里?麻烦给指点下

如何通过Header 发送 access_token

请问如何通过Header 发送 access_token 呢?我看到测试例子里边用的都是get请求,而且我试过把access_token放到Header里边,,,无效的,,不知道怎么配置呢

出现一个反序列化错误

我这边换了mysql数据库,配置文件也改成mysql的了,可是为什么请求的时候出现反序列化错误。
日志打印的sql去数据库查询了,没有错误。数据库的字段也是项目启动自动生成的,数据也初始化进去了。
错误信息:{
"error": "unauthorized",
"error_description": "could not deserialize; nested exception is org.hibernate.type.SerializationException: could not deserialize"
}

/uaa/oauth/token?grant_type=password 返回401

localhost:8080/uaa/oauth/token?grant_type=password&username=admin&password=admin
返回401,调试发现根本没进入到用户名密码认证环节,只有我一个人碰到这个情况吗?

comment: 是我参数写错

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.