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

52 篇文章 2 订阅
48 篇文章 1 订阅

https://www.jb51.net/article/136129.htm

这篇文章主要介绍了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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

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.

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

@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

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@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();

 }

}

?

1

2

3

4

5

6

7

8

@RestController

public class UserController {

 

 @GetMapping("/user")

 public Principal user(Principal user){

  return user;

 }

}

2.3 安全配置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

@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 配置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

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服务配置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

@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的地址即可:

?

1

2

3

4

5

6

security:

 oauth2:

 resource:

  id: order-service

  user-info-uri: http://localhost:8080/uaa/user

  prefer-token-info: false

3.3 权限测试控制器

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

?

1

2

3

4

5

6

7

8

@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支持

?

1

2

3

4

5

6

7

8

9

@Configuration

@EnableOAuth2Sso

public class SecurityConfig extends WebSecurityConfigurerAdapter{

 @Override

 protected void configure(HttpSecurity http) throws Exception {

 

  http.csrf().disable();

 }

}

4.2 配置

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

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

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

您可能感兴趣的文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hello_world!

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值