Spring Cloud下基于OAUTH2認(rèn)證授權(quán)的實(shí)現(xiàn)示例
在Spring Cloud
需要使用OAUTH2
來實(shí)現(xiàn)多個微服務(wù)的統(tǒng)一認(rèn)證授權(quán),通過向OAUTH服務(wù)
發(fā)送某個類型的grant type
進(jìn)行集中認(rèn)證和授權(quán),從而獲得access_token
,而這個token是受其他微服務(wù)信任的,我們在后續(xù)的訪問可以通過access_token
來進(jìn)行,從而實(shí)現(xiàn)了微服務(wù)的統(tǒng)一認(rèn)證授權(quán)。
本示例提供了四大部分:
discovery-service
:服務(wù)注冊和發(fā)現(xiàn)的基本模塊auth-server
:OAUTH2認(rèn)證授權(quán)中心order-service
:普通微服務(wù),用來驗(yàn)證認(rèn)證和授權(quán)api-gateway
:邊界網(wǎng)關(guān)(所有微服務(wù)都在它之后)
OAUTH2中的角色:
Resource Server
:被授權(quán)訪問的資源Authotization Server
:OAUTH2認(rèn)證授權(quán)中心Resource Owner
: 用戶Client
:使用API的客戶端(如Android 、IOS、web app)
Grant Type:
Authorization Code
:用在服務(wù)端應(yīng)用之間Implicit
:用在移動app或者web app(這些app是在用戶的設(shè)備上的,如在手機(jī)上調(diào)起微信來進(jìn)行認(rèn)證授權(quán))Resource Owner Password Credentials(password)
:應(yīng)用直接都是受信任的(都是由一家公司開發(fā)的,本例子使用Client Credentials
:用在應(yīng)用API訪問。
1.基礎(chǔ)環(huán)境
使用Postgres
作為賬戶存儲,Redis
作為Token
存儲,使用docker-compose
在服務(wù)器上啟動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服務(wù)配置
Redis
用來存儲token
,服務(wù)重啟后,無需重新獲取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是無用的,可以隨意設(shè)置 .secret("android") .authorizedGrantTypes("password", "authorization_code", "refresh_token") .and() .withClient("webapp") .scopes("xx") .authorizedGrantTypes("implicit"); } }
2.2 Resource服務(wù)配置
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 權(quán)限設(shè)計
采用用戶(SysUser)
角色(SysRole)
權(quán)限(SysAuthotity)
設(shè)置,彼此之間的關(guān)系是多對多
。通過DomainUserDetailsService
加載用戶和權(quán)限。
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 測試數(shù)據(jù)
data.sql
里初始化了兩個用戶admin
->ROLE_ADMIN
->query_demo
,wyf
->ROLE_USER
3.order-service
3.1 Resource服務(wù)配置
@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
是一個簡單的微服務(wù),使用auth-server
進(jìn)行認(rèn)證授權(quán),在它的配置文件指定用戶信息在auth-server
的地址即可:
security: oauth2: resource: id: order-service user-info-uri: http://localhost:8080/uaa/user prefer-token-info: false
3.3 權(quán)限測試控制器
具備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 關(guān)閉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 客戶端調(diào)用
使用Postman
向http://localhost:8080/uaa/oauth/token
發(fā)送請求獲得access_token
(admin用戶的如7f9b54d4-fd25-4a2c-a848-ddf8f119230b
)
admin用戶
wyf用戶
5.2 api-gateway中的webapp調(diào)用
暫時沒有做測試,下次補(bǔ)充。
6 源碼地址
https://github.com/wiselyman/uaa-zuul
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java中Iterator與ListIterator迭代的區(qū)別
本文主要介紹了Java中Iterator與ListIterator迭代的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07Hibernate+JDBC實(shí)現(xiàn)批量插入、更新及刪除的方法詳解
這篇文章主要介紹了Hibernate+JDBC實(shí)現(xiàn)批量插入、更新及刪除的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了Hibernate與JDBC針對數(shù)據(jù)庫的批量操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-11-11Springsecurity Oauth2如何設(shè)置token的過期時間
如果用戶在指定的時間內(nèi)有操作就給token延長有限期,否則到期后自動過期,如何設(shè)置token的過期時間,本文就來詳細(xì)的介紹一下2021-08-08@RequestParam 接收參數(shù)的值為null的處理方式
這篇文章主要介紹了@RequestParam 接收參數(shù)的值為null的處理方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11Java Map 在put值時value值不被覆蓋的解決辦法
這篇文章主要介紹了Java Map 在put值時value值不被覆蓋的解決辦法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-04-04Spring Boot中使用JDBC Templet的方法教程
這篇文章主要給大家介紹了關(guān)于在Spring Boot中使用JDBC Templet的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03java實(shí)現(xiàn)的漢字轉(zhuǎn)五筆功能實(shí)例
這篇文章主要介紹了java實(shí)現(xiàn)的漢字轉(zhuǎn)五筆功能,結(jié)合具體實(shí)例形式分析了java基于字符串遍歷與編碼轉(zhuǎn)換等操作實(shí)現(xiàn)五筆編碼獲取的相關(guān)操作技巧,需要的朋友可以參考下2017-06-06