|
|
@@ -0,0 +1,210 @@ |
|
|
|
package com.tuoheng.gateway.config; |
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
|
import com.alibaba.fastjson.serializer.SerializerFeature; |
|
|
|
import com.auth0.jwt.JWT; |
|
|
|
import com.auth0.jwt.interfaces.DecodedJWT; |
|
|
|
import com.tuoheng.gateway.model.ClientUserRoleDto; |
|
|
|
import com.tuoheng.gateway.ustil.EncryptUtil; |
|
|
|
import io.micrometer.core.instrument.util.StringUtils; |
|
|
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain; |
|
|
|
import org.springframework.cloud.gateway.filter.GlobalFilter; |
|
|
|
import org.springframework.context.annotation.Configuration; |
|
|
|
import org.springframework.core.Ordered; |
|
|
|
import org.springframework.core.io.buffer.DataBuffer; |
|
|
|
import org.springframework.http.HttpStatus; |
|
|
|
import org.springframework.http.server.reactive.ServerHttpRequest; |
|
|
|
import org.springframework.http.server.reactive.ServerHttpResponse; |
|
|
|
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; |
|
|
|
import org.springframework.util.AntPathMatcher; |
|
|
|
import org.springframework.web.server.ServerWebExchange; |
|
|
|
import reactor.core.publisher.Mono; |
|
|
|
|
|
|
|
import java.nio.charset.StandardCharsets; |
|
|
|
import java.util.*; |
|
|
|
|
|
|
|
|
|
|
|
@Configuration |
|
|
|
public class GatewayFilterConfig implements GlobalFilter, Ordered { |
|
|
|
|
|
|
|
private static final String USERNAME = "username"; |
|
|
|
|
|
|
|
private static final String OUSERID = "oUserId"; |
|
|
|
|
|
|
|
private static final String SCOPE = "scope"; |
|
|
|
|
|
|
|
private static final String CLIENTROLELIST = "clientRoleList"; |
|
|
|
|
|
|
|
private static final String ADMIN = "admin"; |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { |
|
|
|
//todo:header里封装 Client-Id 信息 |
|
|
|
/*String clientId = getClientId(exchange); |
|
|
|
if(StringUtils.isEmpty(clientId)){ |
|
|
|
return invalidClientIdMono(exchange); |
|
|
|
} |
|
|
|
String requestUrl = exchange.getRequest().getPath().value(); |
|
|
|
//todo:获取当前系统、当前接口 可以访问的角色集合 start |
|
|
|
Map<String, List<Integer>> permissionMap = getPermissionByClientId(clientId); |
|
|
|
List<Integer> roleIds = permissionMap.get(requestUrl);*/ |
|
|
|
//todo:获取当前系统、当前接口 可以访问的角色集合 end |
|
|
|
String token = getToken(exchange); |
|
|
|
String username = null; |
|
|
|
Long oUserId = null; |
|
|
|
List<String> authorityList = new ArrayList<>(); |
|
|
|
List<ClientUserRoleDto> clientUserRoleDtoList = new ArrayList<>(); |
|
|
|
if (!StringUtils.isBlank(token)) { |
|
|
|
//token数据解析 |
|
|
|
DecodedJWT decodedJWT = JWT.decode(token); |
|
|
|
username = decodedJWT.getClaim(USERNAME).asString(); |
|
|
|
oUserId = decodedJWT.getClaim(OUSERID).asLong(); |
|
|
|
authorityList = decodedJWT.getClaim(SCOPE).asList(String.class); |
|
|
|
clientUserRoleDtoList = decodedJWT.getClaim(CLIENTROLELIST).asList(ClientUserRoleDto.class); |
|
|
|
} |
|
|
|
/*if(roleIds != null){ |
|
|
|
//说明这个url 需要一定的角色才可以访问 |
|
|
|
//在不是admin权限的情况下进行校验 |
|
|
|
if(!authorityList.contains(ADMIN)){ |
|
|
|
//获取用户 client_id 对应的 roleId |
|
|
|
ClientUserRoleDto clientUserRoleDto = clientUserRoleDtoList.stream().filter(dto -> dto.getClientId().equals(clientId)) |
|
|
|
.findFirst().orElse(null); |
|
|
|
if(Objects.isNull(clientUserRoleDto)){ |
|
|
|
return forbiddenTokenMono(exchange); |
|
|
|
} |
|
|
|
Integer roleId = clientUserRoleDto.getRoleId(); |
|
|
|
if(!roleIds.contains(roleId)){ |
|
|
|
return forbiddenTokenMono(exchange); |
|
|
|
} |
|
|
|
} |
|
|
|
}*/ |
|
|
|
|
|
|
|
if (!StringUtils.isBlank(token)) { |
|
|
|
JSONObject jsonObject = new JSONObject(); |
|
|
|
jsonObject.put(USERNAME, username); |
|
|
|
jsonObject.put(OUSERID, oUserId); |
|
|
|
String base64 = EncryptUtil.encodeUTF8StringBase64(jsonObject.toJSONString()); |
|
|
|
try { |
|
|
|
ServerHttpRequest tokenRequest = exchange.getRequest().mutate().header("th-token", token) |
|
|
|
.header("o-user-json", base64) |
|
|
|
.build(); |
|
|
|
ServerWebExchange build = exchange.mutate().request(tokenRequest).build(); |
|
|
|
return chain.filter(build); |
|
|
|
} catch (InvalidTokenException e) { |
|
|
|
return invalidTokenMono(exchange); |
|
|
|
} |
|
|
|
} |
|
|
|
return chain.filter(exchange); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 获取token |
|
|
|
*/ |
|
|
|
private String getToken(ServerWebExchange exchange) { |
|
|
|
try { |
|
|
|
String tokenStr = exchange.getRequest().getHeaders().getFirst("Authorization"); |
|
|
|
if (StringUtils.isBlank(tokenStr)) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
if (!tokenStr.startsWith("Bearer ")) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
String token = tokenStr.split("Bearer ")[1]; |
|
|
|
if (StringUtils.isBlank(token)) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
return token; |
|
|
|
} catch (Exception e) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private String getClientId(ServerWebExchange exchange) { |
|
|
|
try { |
|
|
|
String clientIdStr = exchange.getRequest().getHeaders().getFirst("Client-Id"); |
|
|
|
if (StringUtils.isBlank(clientIdStr)) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
return clientIdStr; |
|
|
|
} catch (Exception e) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 401 无效的token |
|
|
|
*/ |
|
|
|
private Mono<Void> invalidTokenMono(ServerWebExchange exchange) { |
|
|
|
JSONObject json = new JSONObject(); |
|
|
|
json.put("code", HttpStatus.UNAUTHORIZED.value()); |
|
|
|
json.put("msg", "无效的授权Authorization信息"); |
|
|
|
json.put("data", null); |
|
|
|
return buildReturnMono(json, exchange, HttpStatus.UNAUTHORIZED); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 401 无效的clientId |
|
|
|
*/ |
|
|
|
private Mono<Void> invalidClientIdMono(ServerWebExchange exchange) { |
|
|
|
JSONObject json = new JSONObject(); |
|
|
|
json.put("code", HttpStatus.UNAUTHORIZED.value()); |
|
|
|
json.put("msg", "无效的Client-Id信息"); |
|
|
|
json.put("data", null); |
|
|
|
return buildReturnMono(json, exchange, HttpStatus.UNAUTHORIZED); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 403 未授权的token |
|
|
|
*/ |
|
|
|
private Mono<Void> forbiddenTokenMono(ServerWebExchange exchange) { |
|
|
|
JSONObject json = new JSONObject(); |
|
|
|
json.put("code", HttpStatus.FORBIDDEN.value()); |
|
|
|
json.put("msg", "暂无权限访问"); |
|
|
|
json.put("data", null); |
|
|
|
return buildReturnMono(json, exchange, HttpStatus.FORBIDDEN); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Mono<Void> noTokenMono(ServerWebExchange exchange) { |
|
|
|
JSONObject json = new JSONObject(); |
|
|
|
json.put("code", HttpStatus.UNAUTHORIZED.value()); |
|
|
|
json.put("msg", "未获取到请求头授权Authorization信息"); |
|
|
|
json.put("data", null); |
|
|
|
return buildReturnMono(json, exchange, HttpStatus.UNAUTHORIZED); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Mono<Void> buildReturnMono(JSONObject json, ServerWebExchange exchange, HttpStatus httpStatus) { |
|
|
|
ServerHttpResponse response = exchange.getResponse(); |
|
|
|
byte[] bits = JSONObject.toJSONString(json, SerializerFeature.WriteMapNullValue).getBytes(StandardCharsets.UTF_8); |
|
|
|
DataBuffer buffer = response.bufferFactory().wrap(bits); |
|
|
|
response.setStatusCode(httpStatus); |
|
|
|
//指定编码,否则在浏览器中会中文乱码 |
|
|
|
response.getHeaders().add("Content-Type", "application/json;charset:utf-8"); |
|
|
|
return response.writeWith(Mono.just(buffer)); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据 clientId 从业务系统获取 permission - role 数据 |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
private Map<String, List<Integer>> getPermissionByClientId(String clientId){ |
|
|
|
// permissionUrl - roleIdList |
|
|
|
Map<String, List<Integer>> map = new HashMap<>(); |
|
|
|
if(clientId.equals("tuoheng-oidc-admin")){ |
|
|
|
List<Integer> roleIds = new ArrayList<>(); |
|
|
|
roleIds.add(1001); |
|
|
|
roleIds.add(1002); |
|
|
|
map.put("/oidc/admin/user/create", roleIds); |
|
|
|
} |
|
|
|
return map; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public int getOrder() { |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |