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

网友投稿 291 2023-02-14


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:euFjwqjH5432/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{

@OverrideuFjwqjHe

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 源码地址

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:详解ES6通过WeakMap解决内存泄漏问题
下一篇:详解react关于事件绑定this的四种方式
相关文章

 发表评论

暂时没有评论,来抢沙发吧~