这篇文章给大家介绍如何进行spring cloud gateway oauth整合,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
spring cloud gateway 细粒度配置 spring cloud 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整合就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/dev/204601.html