From 7b7615c68ff5d0c550ae224b52b9c2f65120f172 Mon Sep 17 00:00:00 2001 From: lbw Date: Fri, 7 Apr 2023 18:03:01 +0800 Subject: [PATCH] =?UTF-8?q?:zap:=20=E4=BC=98=E5=8C=96=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF=E6=A8=A1=E5=BC=8F=E4=B8=8B=20NPE=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pigx/auth/endpoint/PigxTokenEndpoint.java | 308 +++++++++--------- 1 file changed, 159 insertions(+), 149 deletions(-) diff --git a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/PigxTokenEndpoint.java b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/PigxTokenEndpoint.java index 4d399ec9d..dcac9bb14 100644 --- a/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/PigxTokenEndpoint.java +++ b/pigx-auth/src/main/java/com/pig4cloud/pigx/auth/endpoint/PigxTokenEndpoint.java @@ -78,178 +78,188 @@ import java.util.stream.Collectors; @RequestMapping("/token") public class PigxTokenEndpoint { - private final PigxAuthenticationFailureEventHandler authenticationFailureHandler; + private final PigxAuthenticationFailureEventHandler authenticationFailureHandler; - private final OAuth2AuthorizationService authorizationService; + private final OAuth2AuthorizationService authorizationService; - private final RemoteClientDetailsService clientDetailsService; + private final RemoteClientDetailsService clientDetailsService; - private final RedisTemplate redisTemplate; + private final RedisTemplate redisTemplate; - private final RemoteTenantService tenantService; + private final RemoteTenantService tenantService; - private final KeyStrResolver tenantKeyStrResolver; + private final KeyStrResolver tenantKeyStrResolver; - private final CacheManager cacheManager; + private final CacheManager cacheManager; - /** - * 认证页面 - * @param modelAndView - * @param error 表单登录失败处理回调的错误信息 - * @return ModelAndView - */ - @GetMapping("/login") - public ModelAndView require(ModelAndView modelAndView, @RequestParam(required = false) String error) { - modelAndView.setViewName("ftl/login"); - modelAndView.addObject("error", error); + /** + * 认证页面 + * + * @param modelAndView + * @param error 表单登录失败处理回调的错误信息 + * @return ModelAndView + */ + @GetMapping("/login") + public ModelAndView require(ModelAndView modelAndView, @RequestParam(required = false) String error) { + modelAndView.setViewName("ftl/login"); + modelAndView.addObject("error", error); - R> tenantList = tenantService.list(SecurityConstants.FROM_IN); - modelAndView.addObject("tenantList", tenantList.getData()); - return modelAndView; - } + R> tenantList = tenantService.list(SecurityConstants.FROM_IN); + modelAndView.addObject("tenantList", tenantList.getData()); + return modelAndView; + } - @GetMapping("/confirm_access") - public ModelAndView confirm(Principal principal, ModelAndView modelAndView, - @RequestParam(OAuth2ParameterNames.CLIENT_ID) String clientId, - @RequestParam(OAuth2ParameterNames.SCOPE) String scope, - @RequestParam(OAuth2ParameterNames.STATE) String state) { - SysOauthClientDetails clientDetails = RetOps - .of(clientDetailsService.getClientDetailsById(clientId, SecurityConstants.FROM_IN)).getData() - .orElseThrow(() -> new OAuthClientException("clientId 不合法")); + @GetMapping("/confirm_access") + public ModelAndView confirm(Principal principal, ModelAndView modelAndView, + @RequestParam(OAuth2ParameterNames.CLIENT_ID) String clientId, + @RequestParam(OAuth2ParameterNames.SCOPE) String scope, + @RequestParam(OAuth2ParameterNames.STATE) String state) { + SysOauthClientDetails clientDetails = RetOps + .of(clientDetailsService.getClientDetailsById(clientId, SecurityConstants.FROM_IN)).getData() + .orElseThrow(() -> new OAuthClientException("clientId 不合法")); - Set authorizedScopes = StringUtils.commaDelimitedListToSet(clientDetails.getScope()); - modelAndView.addObject("clientId", clientId); - modelAndView.addObject("state", state); - modelAndView.addObject("scopeList", authorizedScopes); - modelAndView.addObject("principalName", principal.getName()); - modelAndView.setViewName("ftl/confirm"); - return modelAndView; - } + Set authorizedScopes = StringUtils.commaDelimitedListToSet(clientDetails.getScope()); + modelAndView.addObject("clientId", clientId); + modelAndView.addObject("state", state); + modelAndView.addObject("scopeList", authorizedScopes); + modelAndView.addObject("principalName", principal.getName()); + modelAndView.setViewName("ftl/confirm"); + return modelAndView; + } - /** - * 退出并删除token - * @param authHeader Authorization - */ - @DeleteMapping("/logout") - public R logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader) { - if (StrUtil.isBlank(authHeader)) { - return R.ok(); - } + /** + * 退出并删除token + * + * @param authHeader Authorization + */ + @DeleteMapping("/logout") + public R logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader) { + if (StrUtil.isBlank(authHeader)) { + return R.ok(); + } - String tokenValue = authHeader.replace(OAuth2AccessToken.TokenType.BEARER.getValue(), StrUtil.EMPTY).trim(); - return removeToken(tokenValue); - } + String tokenValue = authHeader.replace(OAuth2AccessToken.TokenType.BEARER.getValue(), StrUtil.EMPTY).trim(); + return removeToken(tokenValue); + } - /** - * 校验token - * @param token 令牌 - * @return - */ - @SneakyThrows - @GetMapping("/check_token") - public R checkToken(String token, HttpServletResponse response, HttpServletRequest request) { - ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response); + /** + * 校验token + * + * @param token 令牌 + * @return + */ + @SneakyThrows + @GetMapping("/check_token") + public R checkToken(String token, HttpServletResponse response, HttpServletRequest request) { + ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response); - if (StrUtil.isBlank(token)) { - httpResponse.setStatusCode(HttpStatus.UNAUTHORIZED); - this.authenticationFailureHandler.onAuthenticationFailure(request, response, - new InvalidBearerTokenException(OAuth2ErrorCodesExpand.TOKEN_MISSING)); - return R.failed(); - } - OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); + if (StrUtil.isBlank(token)) { + httpResponse.setStatusCode(HttpStatus.UNAUTHORIZED); + this.authenticationFailureHandler.onAuthenticationFailure(request, response, + new InvalidBearerTokenException(OAuth2ErrorCodesExpand.TOKEN_MISSING)); + return R.failed(); + } + OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); - // 如果令牌不存在 返回401 - if (authorization == null || authorization.getAccessToken() == null) { - this.authenticationFailureHandler.onAuthenticationFailure(request, response, - new InvalidBearerTokenException(OAuth2ErrorCodesExpand.INVALID_BEARER_TOKEN)); - } + // 如果令牌不存在 返回401 + if (authorization == null || authorization.getAccessToken() == null) { + this.authenticationFailureHandler.onAuthenticationFailure(request, response, + new InvalidBearerTokenException(OAuth2ErrorCodesExpand.INVALID_BEARER_TOKEN)); + } - // 获取令牌 - return R.ok(Objects.requireNonNull(authorization).getAccessToken().getToken()); - } + // 获取令牌 + return R.ok(Objects.requireNonNull(authorization).getAccessToken().getToken()); + } - /** - * 令牌管理调用 - * @param token token - */ - @Inner - @DeleteMapping("/{token}") - public R removeToken(@PathVariable("token") String token) { - OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); - if (authorization == null) { - return R.ok(); - } + /** + * 令牌管理调用 + * + * @param token token + */ + @Inner + @DeleteMapping("/{token}") + public R removeToken(@PathVariable("token") String token) { + OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); + if (authorization == null) { + return R.ok(); + } - OAuth2Authorization.Token accessToken = authorization.getAccessToken(); - if (accessToken == null || StrUtil.isBlank(accessToken.getToken().getTokenValue())) { - return R.ok(); - } - // 清空用户信息 - cacheManager.getCache(CacheConstants.USER_DETAILS).evict(authorization.getPrincipalName()); - // 清空access token - authorizationService.remove(authorization); - // 处理自定义退出事件,保存相关日志 - SpringContextHolder.publishEvent(new LogoutSuccessEvent(new PreAuthenticatedAuthenticationToken( - authorization.getPrincipalName(), authorization.getRegisteredClientId()))); - return R.ok(); - } + OAuth2Authorization.Token accessToken = authorization.getAccessToken(); + if (accessToken == null || StrUtil.isBlank(accessToken.getToken().getTokenValue())) { + return R.ok(); + } + // 清空用户信息 + cacheManager.getCache(CacheConstants.USER_DETAILS).evict(authorization.getPrincipalName()); + // 清空access token + authorizationService.remove(authorization); + // 处理自定义退出事件,保存相关日志 + SpringContextHolder.publishEvent(new LogoutSuccessEvent(new PreAuthenticatedAuthenticationToken( + authorization.getPrincipalName(), authorization.getRegisteredClientId()))); + return R.ok(); + } - /** - * 查询token - * @param params 分页参数 - * @return - */ - @Inner - @PostMapping("/page") - public R> tokenList(@RequestBody Map params) { - // 根据分页参数获取对应数据 - String key = String.format("%s::%s::*", tenantKeyStrResolver.key(), CacheConstants.PROJECT_OAUTH_ACCESS); - int current = MapUtil.getInt(params, CommonConstants.CURRENT); - int size = MapUtil.getInt(params, CommonConstants.SIZE); - Set keys = redisTemplate.keys(key); - List pages = keys.stream().skip((current - 1) * size).limit(size).collect(Collectors.toList()); - Page result = new Page(current, size); + /** + * 查询token + * + * @param params 分页参数 + * @return + */ + @Inner + @PostMapping("/page") + public R> tokenList(@RequestBody Map params) { + // 根据分页参数获取对应数据 + String key = String.format("%s::%s::*", tenantKeyStrResolver.key(), CacheConstants.PROJECT_OAUTH_ACCESS); + int current = MapUtil.getInt(params, CommonConstants.CURRENT); + int size = MapUtil.getInt(params, CommonConstants.SIZE); + Set keys = redisTemplate.keys(key); + List pages = keys.stream().skip((current - 1) * size).limit(size).collect(Collectors.toList()); + Page result = new Page(current, size); - List tokenVoList = redisTemplate.opsForValue().multiGet(pages).stream().map(obj -> { - OAuth2Authorization authorization = (OAuth2Authorization) obj; - TokenVo tokenVo = new TokenVo(); - tokenVo.setClientId(authorization.getRegisteredClientId()); - tokenVo.setId(authorization.getId()); - tokenVo.setUsername(authorization.getPrincipalName()); - OAuth2Authorization.Token accessToken = authorization.getAccessToken(); - tokenVo.setAccessToken(accessToken.getToken().getTokenValue()); + List tokenVoList = redisTemplate.opsForValue().multiGet(pages).stream().map(obj -> { + OAuth2Authorization authorization = (OAuth2Authorization) obj; + TokenVo tokenVo = new TokenVo(); + tokenVo.setClientId(authorization.getRegisteredClientId()); + tokenVo.setId(authorization.getId()); + tokenVo.setUsername(authorization.getPrincipalName()); + OAuth2Authorization.Token accessToken = authorization.getAccessToken(); + tokenVo.setAccessToken(accessToken.getToken().getTokenValue()); - String expiresAt = TemporalAccessorUtil.format(accessToken.getToken().getExpiresAt(), - DatePattern.NORM_DATETIME_PATTERN); - tokenVo.setExpiresAt(expiresAt); + String expiresAt = TemporalAccessorUtil.format(accessToken.getToken().getExpiresAt(), + DatePattern.NORM_DATETIME_PATTERN); + tokenVo.setExpiresAt(expiresAt); - String issuedAt = TemporalAccessorUtil.format(accessToken.getToken().getIssuedAt(), - DatePattern.NORM_DATETIME_PATTERN); - tokenVo.setIssuedAt(issuedAt); + String issuedAt = TemporalAccessorUtil.format(accessToken.getToken().getIssuedAt(), + DatePattern.NORM_DATETIME_PATTERN); + tokenVo.setIssuedAt(issuedAt); - Map attributes = authorization.getAttributes(); - Authentication authentication = (Authentication) attributes.get(Principal.class.getName()); - PigxUser pigxUser = (PigxUser) authentication.getPrincipal(); - tokenVo.setUserId(pigxUser.getId()); - return tokenVo; - }).filter(tokenVo -> { - // 根据用户名过滤 - String username = MapUtil.getStr(params, SecurityConstants.DETAILS_USERNAME); - if (StrUtil.isBlank(username)) { - return true; - } - return tokenVo.getUsername().contains(username); - }).collect(Collectors.toList()); - result.setRecords(tokenVoList); - result.setTotal(keys.size()); - return R.ok(result); - } + Map attributes = authorization.getAttributes(); + Authentication authentication = (Authentication) attributes.get(Principal.class.getName()); - @Inner - @GetMapping("/query-token") - public R queryToken(String token) { - OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); - return R.ok(authorization); - } + if (Objects.isNull(authentication)) { + return tokenVo; + } + + PigxUser pigxUser = (PigxUser) authentication.getPrincipal(); + tokenVo.setUserId(pigxUser.getId()); + return tokenVo; + }).filter(tokenVo -> { + // 根据用户名过滤 + String username = MapUtil.getStr(params, SecurityConstants.DETAILS_USERNAME); + if (StrUtil.isBlank(username)) { + return true; + } + return tokenVo.getUsername().contains(username); + }).collect(Collectors.toList()); + result.setRecords(tokenVoList); + result.setTotal(keys.size()); + return R.ok(result); + } + + @Inner + @GetMapping("/query-token") + public R queryToken(String token) { + OAuth2Authorization authorization = authorizationService.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); + return R.ok(authorization); + } }