Spring Cloud下基于OAUTH2認(rèn)證授權(quán)的實(shí)現(xiàn)示例
在Spring Cloud需要使用OAUTH2來(lái)實(shí)現(xiàn)多個(gè)微服務(wù)的統(tǒng)一認(rèn)證授權(quán),通過(guò)向OAUTH服務(wù)發(fā)送某個(gè)類(lèi)型的grant type進(jìn)行集中認(rèn)證和授權(quán),從而獲得access_token,而這個(gè)token是受其他微服務(wù)信任的,我們?cè)诤罄m(xù)的訪問(wèn)可以通過(guò)access_token來(lái)進(jìn)行,從而實(shí)現(xiàn)了微服務(wù)的統(tǒng)一認(rèn)證授權(quán)。
本示例提供了四大部分:
discovery-service:服務(wù)注冊(cè)和發(fā)現(xiàn)的基本模塊auth-server:OAUTH2認(rèn)證授權(quán)中心order-service:普通微服務(wù),用來(lái)驗(yàn)證認(rèn)證和授權(quán)api-gateway:邊界網(wǎng)關(guān)(所有微服務(wù)都在它之后)
OAUTH2中的角色:
Resource Server:被授權(quán)訪問(wèn)的資源Authotization Server:OAUTH2認(rèn)證授權(quán)中心Resource Owner: 用戶(hù)Client:使用API的客戶(hù)端(如Android 、IOS、web app)
Grant Type:
Authorization Code:用在服務(wù)端應(yīng)用之間Implicit:用在移動(dòng)app或者web app(這些app是在用戶(hù)的設(shè)備上的,如在手機(jī)上調(diào)起微信來(lái)進(jìn)行認(rèn)證授權(quán))Resource Owner Password Credentials(password):應(yīng)用直接都是受信任的(都是由一家公司開(kāi)發(fā)的,本例子使用Client Credentials:用在應(yīng)用API訪問(wèn)。
1.基礎(chǔ)環(huán)境
使用Postgres作為賬戶(hù)存儲(chǔ),Redis作為Token存儲(chǔ),使用docker-compose在服務(wù)器上啟動(dòng)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用來(lái)存儲(chǔ)token,服務(wù)重啟后,無(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是無(wú)用的,可以隨意設(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也是一個(gè)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();
}
//不定義沒(méi)有password grant_type
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
2.4 權(quán)限設(shè)計(jì)
采用用戶(hù)(SysUser) 角色(SysRole) 權(quán)限(SysAuthotity)設(shè)置,彼此之間的關(guān)系是多對(duì)多。通過(guò)DomainUserDetailsService 加載用戶(hù)和權(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 測(cè)試數(shù)據(jù)
data.sql里初始化了兩個(gè)用戶(hù)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 用戶(hù)信息配置
order-service是一個(gè)簡(jiǎn)單的微服務(wù),使用auth-server進(jìn)行認(rèn)證授權(quán),在它的配置文件指定用戶(hù)信息在auth-server的地址即可:
security: oauth2: resource: id: order-service user-info-uri: http://localhost:8080/uaa/user prefer-token-info: false
3.3 權(quán)限測(cè)試控制器
具備authority未query-demo的才能訪問(wèn),即為admin用戶(hù)
@RestController
public class DemoController {
@GetMapping("/demo")
@PreAuthorize("hasAuthority('query-demo')")
public String getDemo(){
return "good";
}
}
4 api-gateway
api-gateway在本例中有2個(gè)作用:
- 本身作為一個(gè)client,使用
implicit - 作為外部app訪問(wèn)的方向代理
4.1 關(guān)閉csrf并開(kāi)啟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 客戶(hù)端調(diào)用
使用Postman向http://localhost:8080/uaa/oauth/token發(fā)送請(qǐng)求獲得access_token(admin用戶(hù)的如7f9b54d4-fd25-4a2c-a848-ddf8f119230b)
admin用戶(hù)



wyf用戶(hù)



5.2 api-gateway中的webapp調(diào)用
暫時(shí)沒(méi)有做測(cè)試,下次補(bǔ)充。
6 源碼地址
https://github.com/wiselyman/uaa-zuul
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot中忽略實(shí)體類(lèi)中的某個(gè)屬性不返回給前端的方法(示例詳解)
本文介紹了在Spring Boot中使用Jackson和Fastjson忽略實(shí)體類(lèi)屬性不返回給前端的方法,在Jackson中,同時(shí)使用@JsonProperty和@JsonIgnore時(shí),@JsonIgnore可能失效,Fastjson中可以使用@JSONField(serialize=false)來(lái)實(shí)現(xiàn),本文結(jié)合實(shí)例代碼介紹的非常詳細(xì),需要的朋友參考下吧2024-11-11
springboot中@ConfigurationProperties無(wú)效果的解決方法
本文主要介紹了springboot中@ConfigurationProperties無(wú)效果,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06
java 線程池keepAliveTime的含義說(shuō)明
這篇文章主要介紹了java 線程池keepAliveTime的含義說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02
idea創(chuàng)建properties文件,解決亂碼問(wèn)題
這篇文章主要介紹了idea創(chuàng)建properties文件,解決亂碼問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
java簡(jiǎn)單讀取properties配置文件的方法示例
這篇文章主要介紹了java簡(jiǎn)單讀取properties配置文件的方法,涉及java針對(duì)properties配置的載入及文件屬性讀取相關(guān)操作技巧,需要的朋友可以參考下2017-09-09
Spring Boot 2 實(shí)戰(zhàn):自定義啟動(dòng)運(yùn)行邏輯實(shí)例詳解
這篇文章主要介紹了Spring Boot 2 實(shí)戰(zhàn):自定義啟動(dòng)運(yùn)行邏輯,結(jié)合實(shí)例形式詳細(xì)分析了Spring Boot 2自定義啟動(dòng)運(yùn)行邏輯詳細(xì)操作技巧與注意事項(xiàng),需要的朋友可以參考下2020-05-05

