日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

gateway权限统一认证

發布時間:2023/12/10 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 gateway权限统一认证 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:

? 之前使用過JWT TOKEN, 所生成的TOKEN過于繁瑣, 且在用戶維度操作上并不能滿足業務需求.

JWT TOKEN自刷新,請點擊此文章了解!

自定義TOKEN實現流程圖:

需求:

1. Token過期時間為60分鐘, 若用戶正在持續操作則應該為token續期 2. 當用戶登陸后,應該可以根據Token獲取對應的用戶,且在系統中用戶只能在一個地方登陸 3. Token對應的權限應該可以進行統一鑒權

創建Token數據模型:

/* token 數據模型 */ public Token {//UUID => TOKEN => Redis KEYprivate String key;//用戶信息 => Redis VALUEprivate User user;// 創建token時間戳private Long createTimestamp;// 當前token所對應的sessionId;private String sessionId;/* 省略 get set 方法 */ } /* 用戶數據模型 */ public User {private String name;private String age;private String gender;// 權限路徑列表private List<String> permissions;/* 省略 get set 方法 */ }

gateway攔截器:

/*** @author zly*/ @Slf4j @Configuration public class HttpRequestFilter implements GlobalFilter, Ordered {@Resourceprivate RedisService redisService;@Resourceprivate WhiteListProperties whiteListProperties;@Value("${spring.profiles.active}")private String env;private final static Long TIME_OUT = 1800000L;/*** 登錄KEY前綴*/private static final String LOGIN_KEY = "LOGIN_KEY";@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest serverHttpRequest = exchange.getRequest();String path = serverHttpRequest.getURI().getPath();String url = null;try {boolean res = false;String[] paths = path.split("/");if ("api".equals(paths[3])) {res = this.isCheckToken(path.split("api")[1]);} else {res = this.isCheckToken(paths[3]);}if (res) {url = path.split("api")[1];}} catch (Exception e) {// nothing}/* 參數校驗 */this.checkParams(serverHttpRequest.getQueryParams());/* 權限校驗 */if (StringUtils.isNotBlank(url)) {/* 校驗請求token是否過期 */UserVO user = this.checkToken(serverHttpRequest);/* 白名單 */if (!whiteListProperties.getWhiteList().contains(url)) {/* 校驗權限 */this.checkPermission(url, user.getPermissionUrls());}}return chain.filter(exchange);}private boolean isCheckToken(String path) {List<String> notCheckToken = whiteListProperties.getNotCheckToken();for (String url : notCheckToken) {if (url.contains(path)) {return false;}}return true;}private UserVO checkToken(ServerHttpRequest serverHttpRequest) {String token = serverHttpRequest.getHeaders().getFirst("token");ObjectMapper objectMapper = new ObjectMapper();Object key = redisService.getKey(LOGIN_KEY + token);if (Objects.isNull(key)) {throw new AuthException("登錄超時,請重新登錄!");}UserVO user = objectMapper.convertValue(key, UserVO.class);if (System.currentTimeMillis() - user.getTimestamp() > TIME_OUT) {/* 取出記錄的時間戳與當前時間對比 若大于半小時則更新緩存,自動續期 */user.setTimestamp(System.currentTimeMillis());redisService.insert(LOGIN_KEY + token, user, 60, TimeUnit.MINUTES);}return user;}@Overridepublic int getOrder() {return 0;}/*** 參數校驗** @param params 參數Map*/private void checkParams(MultiValueMap<String, String> params) {params.forEach((k, v) -> {String param = v.toString().toUpperCase();if (param.contains(ASTERISK) || param.contains(SINGLE_QUOTES)|| param.contains(WITH) || param.contains(QUESTION_MARK)|| param.contains(AND) || param.contains(SELECT)|| param.contains(OR) || param.contains(WHERE)|| param.contains(DROP) || param.contains(UPDATE)|| param.contains(SET) || param.contains(DELETE)|| param.contains(FROM) || param.contains(INSERT)|| param.contains(ILLEGAL_CHARACTER)) {throw new IllegalCharacterException("輸入非法參數 : " + v.toString());}});}/*** 權限校驗** @param url 訪問路徑*/private void checkPermission(String url, List<String> permissionUrls) {/* 開發環境省略權限校驗 */if ("dev".equals(env)){return;}/* 權限路徑匹配 */for (String permissionUrl : permissionUrls) {if (url.contains(permissionUrl)) {return;}}throw new ServiceException("權限不足!");} }

異常攔截并統一返回:

/*** 覆蓋默認的異常處理** @author yinjihuan*/ @Configuration @EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class}) public class ErrorHandlerConfiguration {private final ServerProperties serverProperties;private final ApplicationContext applicationContext;private final ResourceProperties resourceProperties;private final List<ViewResolver> viewResolvers;private final ServerCodecConfigurer serverCodecConfigurer;public ErrorHandlerConfiguration(ServerProperties serverProperties,ResourceProperties resourceProperties,ObjectProvider<List<ViewResolver>> viewResolversProvider,ServerCodecConfigurer serverCodecConfigurer,ApplicationContext applicationContext) {this.serverProperties = serverProperties;this.applicationContext = applicationContext;this.resourceProperties = resourceProperties;this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);this.serverCodecConfigurer = serverCodecConfigurer;}@Bean@Order(Ordered.HIGHEST_PRECEDENCE)public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {JsonExceptionHandler exceptionHandler = new JsonExceptionHandler(errorAttributes,this.resourceProperties,this.serverProperties.getError(),this.applicationContext);exceptionHandler.setViewResolvers(this.viewResolvers);exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());return exceptionHandler;}}

自定義用戶認證異常:

/*** 自定義異常處理** <p>異常時用JSON代替HTML異常信息<p>** @author yinjihuan*/ public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler {public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties,ErrorProperties errorProperties, ApplicationContext applicationContext) {super(errorAttributes, resourceProperties, errorProperties, applicationContext);}/*** 獲取異常屬性*/@Overrideprotected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {int code = HttpStatus.INTERNAL_SERVER_ERROR.value();Throwable error = super.getError(request);/* 處理全局自定義異常類攔截 */if (error instanceof org.springframework.cloud.gateway.support.NotFoundException) {code = HttpStatus.NOT_FOUND.value();}if (error instanceof com.wisdom.pojo.exception.IllegalUrlException) {code = HttpStatus.BAD_REQUEST.value();}if (error instanceof com.wisdom.pojo.exception.IllegalCharacterException) {code = HttpStatus.NOT_ACCEPTABLE.value();}if (error instanceof com.wisdom.pojo.exception.AuthException) {code = HttpStatus.UNAUTHORIZED.value();}if (error instanceof com.wisdom.pojo.exception.ServiceException) {return response(HttpStatus.OK.value(), HttpStatus.BAD_REQUEST.value(), error.getMessage());}if (error instanceof org.springframework.web.server.ResponseStatusException) {code = HttpStatus.NOT_FOUND.value();}if (error instanceof com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException) {return response(HttpStatus.OK.value(), HttpStatus.SERVICE_UNAVAILABLE.value(),"訪問頻率過高,請稍后訪問!");}if (error instanceof com.alibaba.csp.sentinel.slots.block.flow.FlowException) {return response(HttpStatus.OK.value(), HttpStatus.SERVICE_UNAVAILABLE.value(),"訪問頻率過高,請稍后訪問!");}return response(code, code, this.buildMessage(request, error));}/*** 指定響應處理方法為JSON處理的方法** @param errorAttributes 錯誤屬性*/@Overrideprotected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);}/*** 根據code獲取對應的HttpStatus** @param errorAttributes 錯誤屬性* @return httpStatus*/@Overrideprotected int getHttpStatus(Map<String, Object> errorAttributes) {int statusCode = (int) errorAttributes.get("http-code");HttpStatus httpStatus = HttpStatus.valueOf(statusCode);return httpStatus.value();}/*** 構建異常信息** @param request 請求域* @param ex 錯誤類* @return String*/private String buildMessage(ServerRequest request, Throwable ex) {StringBuilder message = new StringBuilder("Failed to handle request [");message.append(request.methodName());message.append(" ");message.append(request.uri());message.append("]");if (ex != null) {message.append(": ");message.append(ex.getMessage());}return message.toString();}/*** 構建返回的JSON數據格式** @param status 狀態碼* @param errorMessage 異常信息* @return Map*/public static Map<String, Object> response(int httpCode, int status, String errorMessage) {Map<String, Object> map = new HashMap<>(3);map.put("http-code", httpCode);map.put("code", status);map.put("message", errorMessage);map.put("data", null);return map;}}

源碼地址:

在線自定義TOKEN源碼地址

總結

以上是生活随笔為你收集整理的gateway权限统一认证的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。