这篇文章给大家介绍如何进行spring cloud gateway oauth整合,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth3-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
简易校验
/**
* * 程序名 : AccessFilter 建立日期: 2018-09-09 作者 : someday 模块 : 网关 描述 : oauth校验 备注 :
* version20180909001
* <p>
* 修改历史 序号 日期 修改人 修改原因
*/
@Component
public class AccessFilter implements GlobalFilter, Ordered {
// url匹配器
private AntPathMatcher pathMatcher = new AntPathMatcher();
@Resource
private RedisTemplate<String, Object> redisTemplate;
@Resource
private AuthIgnored authIgnored;
@Override
public int getOrder() {
// TODO Auto-generated method stub
return -500;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// TODO Auto-generated method stub
String accessToken = TokenUtil.extractToken(exchange.getRequest());
// 默认
boolean flag = false;
for (String ignored : authIgnored.getIgnored()) {
if (pathMatcher.match(ignored, exchange.getRequest().getPath().value())) {
flag = true; // 白名单
}
}
if (flag) {
return chain.filter(exchange);
} else {
Map<String, Object> params = (Map<String, Object>) redisTemplate.opsForValue().get(UaaConstant.TOKEN+":" + accessToken);
if (params != null) {
return chain.filter(exchange);
} else {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
ServerHttpResponse response = exchange.getResponse();
JSONObject message = new JSONObject();
message.put("resp_code", 401);
message.put("resp_msg", "未认证通过!");
byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bits);
response.setStatusCode(HttpStatus.UNAUTHORIZED);
// 指定编码,否则在浏览器中会中文乱码
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
}
}
}
}
配置资源服务器
package com.open.capacity.client.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.security.reactive.EndpointRequest;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth3.common.OAuth3AccessToken;
import org.springframework.security.oauth3.provider.token.TokenStore;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.authentication.AuthenticationWebFilter;
import org.springframework.web.server.WebFilter;
import com.open.capacity.client.handler.ResAccessDeniedHandler;
import com.open.capacity.client.handler.ResAuthenticationEntryPoint;
import com.open.capacity.client.handler.ResAuthenticationFailureHandler;
import com.open.capacity.client.handler.ResAuthenticationSuccessHandler;
import com.open.capacity.client.token.AuthorizeConfigManager;
import com.open.capacity.client.token.TokenAuthenticationConverter;
import com.open.capacity.client.token.TokenAuthenticationManager;
import com.open.capacity.common.auth.props.PermitUrlProperties;
/**
* 资源服务器UAAClientAutoConfig
*/
@Configuration
@EnableConfigurationProperties(PermitUrlProperties.class)
public class UAAClientAutoConfig {
@Autowired
private PermitUrlProperties permitUrlProperties;
@Autowired
private TokenStore tokenStore;
@Autowired
private AuthorizeConfigManager authorizeConfigManager ;
// @Resource(name="delegatingAuthorizationManager")
// private DelegatingReactiveAuthorizationManager delegatingAuthorizationManager;
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
//认证处理器
ReactiveAuthenticationManager tokenAuthenticationManager = new TokenAuthenticationManager(tokenStore);
ResAuthenticationEntryPoint resAuthenticationEntryPoint = new ResAuthenticationEntryPoint();
ResAccessDeniedHandler resAccessDeniedHandler = new ResAccessDeniedHandler() ;
//构建Bearer Token
//请求参数强制加上 Authorization BEARER token
http.addFilterAt((WebFilter) (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
if(request.getQueryParams().getFirst("access_token")!=null) {
exchange.getRequest().mutate().headers(httpHeaders ->
httpHeaders.add(
"Authorization",
OAuth3AccessToken.BEARER_TYPE+" "+request.getQueryParams().getFirst("access_token"))
);
}
return chain.filter(exchange);
}, SecurityWebFiltersOrder.FIRST);
//身份认证
AuthenticationWebFilter authenticationWebFilter = new AuthenticationWebFilter(tokenAuthenticationManager);
authenticationWebFilter.setAuthenticationFailureHandler(new ResAuthenticationFailureHandler()); //登陆验证失败
authenticationWebFilter.setAuthenticationSuccessHandler(new ResAuthenticationSuccessHandler()); //认证成功
//token转换器
TokenAuthenticationConverter tokenAuthenticationConverter = new TokenAuthenticationConverter();
tokenAuthenticationConverter.setAllowUriQueryParameter(true);
authenticationWebFilter.setServerAuthenticationConverter(tokenAuthenticationConverter);
http.addFilterAt(authenticationWebFilter, SecurityWebFiltersOrder.AUTHENTICATION);
//访问授权
// AuthorizationWebFilter authorizationWebFilter=new AuthorizationWebFilter(delegatingAuthorizationManager);
// http.addFilterAt(authorizationWebFilter, SecurityWebFiltersOrder.FORM_LOGIN);
ServerHttpSecurity.AuthorizeExchangeSpec authorizeExchange = http.authorizeExchange();
authorizeExchange.matchers(EndpointRequest.toAnyEndpoint()).permitAll(); //无需进行权限过滤的请求路径
authorizeExchange.pathMatchers(permitUrlProperties.getIgnored()).permitAll() ;//无需进行权限过滤的请求路径
authorizeExchange
.pathMatchers(HttpMethod.OPTIONS).permitAll() //option 请求默认放行
// .anyExchange().access(authorizeConfigManager) // 应用api权限控制
.anyExchange().authenticated() //token 有效性控制
.and()
.exceptionHandling()
.accessDeniedHandler(resAccessDeniedHandler)
.authenticationEntryPoint(resAuthenticationEntryPoint)
.and()
.headers()
.frameOptions()
.disable()
.and()
.httpBasic().disable()
.csrf().disable();
return http.build();
}
}
token有效期检测
package com.open.capacity.client.token;
import org.springframework.http.HttpStatus;
/*
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth3.common.OAuth3AccessToken;
import org.springframework.security.oauth3.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth3.core.OAuth3AuthenticationException;
import org.springframework.security.oauth3.core.OAuth3Error;
import org.springframework.security.oauth3.provider.OAuth3Authentication;
import org.springframework.security.oauth3.provider.token.TokenStore;
import org.springframework.security.oauth3.server.resource.BearerTokenAuthenticationToken;
import org.springframework.security.oauth3.server.resource.BearerTokenError;
import org.springframework.security.oauth3.server.resource.BearerTokenErrorCodes;
import reactor.core.publisher.Mono;
/**
* A {@link ReactiveAuthenticationManager} for Jwt tokens.
*
* @author Rob Winch
* @since 5.1
*/
public final class TokenAuthenticationManager implements ReactiveAuthenticationManager {
private TokenStore tokenStore;
public TokenAuthenticationManager(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
return Mono.justOrEmpty(authentication)
.filter(a -> a instanceof BearerTokenAuthenticationToken)
.cast(BearerTokenAuthenticationToken.class)
.map(BearerTokenAuthenticationToken::getToken)
.flatMap((accessTokenValue -> {
OAuth3AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue);
if (accessToken == null) {
OAuth3Error error = new BearerTokenError(
BearerTokenErrorCodes.INVALID_TOKEN,
HttpStatus.UNAUTHORIZED,
"Invalid access token: " + accessTokenValue,
"https://tools.ietf.org/html/rfc6750#section-3.1");
return Mono.error(new OAuth3AuthenticationException(error,"Invalid access token: " + accessTokenValue));
} else if (accessToken.isExpired()) {
tokenStore.removeAccessToken(accessToken);
OAuth3Error error = new BearerTokenError(
BearerTokenErrorCodes.INVALID_TOKEN,
HttpStatus.UNAUTHORIZED,
"Access token expired: " + accessTokenValue,
"https://tools.ietf.org/html/rfc6750#section-3.1");
return Mono.error(new OAuth3AuthenticationException(error,"Access token expired: " + accessTokenValue));
}
OAuth3Authentication result = tokenStore.readAuthentication(accessToken);
if (result == null) {
return Mono.error(new InvalidTokenException("Invalid access token: " + accessTokenValue));
}
return Mono.just(result);
}))
.cast(Authentication.class);
}
}
应用可访问API列表控制
package com.open.capacity.client.token;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth3.provider.OAuth3Authentication;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import com.open.capacity.client.dao.SysClientDao;
import com.open.capacity.client.dao.SysServiceDao;
import reactor.core.publisher.Mono;
/**
* @author 作者 owen E-mail: 624191343@qq.com
* @version 创建时间:2018年2月1日 下午9:47:00 类说明
*/
@Component
public class AuthorizeConfigManager implements ReactiveAuthorizationManager<AuthorizationContext> {
@Resource
private SysServiceDao sysServiceDao;
@Resource
private SysClientDao sysClientDao;
private AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication,
AuthorizationContext authorizationContext) {
return authentication.map(auth -> {
// TODO 目前都是true
boolean hasPermission = false;
ServerWebExchange exchange = authorizationContext.getExchange();
ServerHttpRequest request = exchange.getRequest();
if (auth instanceof OAuth3Authentication) {
OAuth3Authentication athentication = (OAuth3Authentication) auth;
String clientId = athentication.getOAuth3Request().getClientId();
Map map = sysClientDao.getClient(clientId);
if (map == null) {
return new AuthorizationDecision(false);
} else {
List<Map> list = sysServiceDao.listByClientId(Long.valueOf(String.valueOf(map.get("id"))));
for (Iterator<Map> it = list.iterator(); it.hasNext();) {
Map temp = it.next();
if (antPathMatcher.match(String.valueOf(temp.get("path")), request.getURI().getPath())) {
return new AuthorizationDecision(true);
}
}
return new AuthorizationDecision(false);
}
}
// boolean isPermission = super.hasPermission(auth,
// request.getMethodValue(), request.getURI().getPath());
return new AuthorizationDecision(hasPermission);
}).defaultIfEmpty(new AuthorizationDecision(false));
}
}
关于如何进行spring cloud gateway oauth整合就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。