diff --git a/youlai-auth/src/main/java/com/youlai/auth/authentication/captcha/CaptchaAuthenticationProvider.java b/youlai-auth/src/main/java/com/youlai/auth/authentication/captcha/CaptchaAuthenticationProvider.java index 3c12391a0..5e21b8da3 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/authentication/captcha/CaptchaAuthenticationProvider.java +++ b/youlai-auth/src/main/java/com/youlai/auth/authentication/captcha/CaptchaAuthenticationProvider.java @@ -1,6 +1,7 @@ package com.youlai.auth.authentication.captcha; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import com.youlai.auth.util.OAuth2AuthenticationProviderUtils; import com.youlai.common.constant.SecurityConstants; @@ -120,6 +121,9 @@ public class CaptchaAuthenticationProvider implements AuthenticationProvider { generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes()); + // 权限数据比较多通过反射移除不持久化至数据库 + ReflectUtil.setFieldValue(usernamePasswordAuthentication.getPrincipal(), "perms", null); + OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient) .principalName(usernamePasswordAuthentication.getName()) .authorizationGrantType(CaptchaAuthenticationToken.CAPTCHA) @@ -150,6 +154,7 @@ public class CaptchaAuthenticationProvider implements AuthenticationProvider { } OAuth2Authorization authorization = authorizationBuilder.build(); + // 持久化令牌发放记录到数据库 this.authorizationService.save(authorization); additionalParameters = Collections.EMPTY_MAP; return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken, refreshToken, additionalParameters); diff --git a/youlai-auth/src/main/java/com/youlai/auth/authentication/password/PasswordAuthenticationProvider.java b/youlai-auth/src/main/java/com/youlai/auth/authentication/password/PasswordAuthenticationProvider.java index 4f1619766..b8dd7fb58 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/authentication/password/PasswordAuthenticationProvider.java +++ b/youlai-auth/src/main/java/com/youlai/auth/authentication/password/PasswordAuthenticationProvider.java @@ -128,14 +128,14 @@ public class PasswordAuthenticationProvider implements AuthenticationProvider { throw new OAuth2AuthenticationException(error); } + OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(), generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes()); - + // 权限数据(perms)比较多通过反射移除,不随令牌一起持久化至数据库 ReflectUtil.setFieldValue(usernamePasswordAuthentication.getPrincipal(), "perms", null); - // 持久化令牌发放记录到数据库 OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient) .principalName(usernamePasswordAuthentication.getName()) .authorizationGrantType(AuthorizationGrantType.PASSWORD) @@ -166,10 +166,12 @@ public class PasswordAuthenticationProvider implements AuthenticationProvider { authorizationBuilder.refreshToken(refreshToken); } - OAuth2Authorization authorization = authorizationBuilder.build(); + + // 持久化令牌发放记录到数据库 this.authorizationService.save(authorization); additionalParameters = Collections.emptyMap(); + return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken, refreshToken, additionalParameters); } diff --git a/youlai-auth/src/main/java/com/youlai/auth/config/AuthorizationServerConfig.java b/youlai-auth/src/main/java/com/youlai/auth/config/AuthorizationServerConfig.java index 04bcd27ca..d20718d8a 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/config/AuthorizationServerConfig.java +++ b/youlai-auth/src/main/java/com/youlai/auth/config/AuthorizationServerConfig.java @@ -87,7 +87,7 @@ public class AuthorizationServerConfig { private final OAuth2TokenCustomizer jwtCustomizer; /** - * 授权配置 + * 授权服务器端点配置 */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) @@ -106,6 +106,7 @@ public class AuthorizationServerConfig { tokenEndpoint .accessTokenRequestConverters( authenticationConverters ->// <1> + // 自定义授权模式转换器(Converter) authenticationConverters.addAll( List.of( new PasswordAuthenticationConverter(), @@ -115,7 +116,8 @@ public class AuthorizationServerConfig { ) ) ) - .authenticationProviders(authenticationProviders ->// <2> + .authenticationProviders(authenticationProviders ->// <2> + // 自定义授权模式提供者(Provider) authenticationProviders.addAll( List.of( new PasswordAuthenticationProvider(authenticationManager, authorizationService, tokenGenerator), @@ -126,7 +128,7 @@ public class AuthorizationServerConfig { ) ) .accessTokenResponseHandler(new MyAuthenticationSuccessHandler()) // 自定义成功响应 - .errorResponseHandler(new MyAuthenticationFailureHandler()) // 自定义异常响应 + .errorResponseHandler(new MyAuthenticationFailureHandler()) // 自定义失败响应 ); @@ -140,15 +142,6 @@ public class AuthorizationServerConfig { } - /* @Bean - public AuthenticationProvider daoAuthenticationProvider() { - DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); - daoAuthenticationProvider.setUserDetailsService(userDetailsService); - daoAuthenticationProvider.setHideUserNotFoundExceptions(false) ; // 抛出用户不存在异常 - return daoAuthenticationProvider ; - }*/ - - @Bean // <5> public JWKSource jwkSource() { KeyPair keyPair = generateRsaKey(); @@ -261,8 +254,11 @@ public class AuthorizationServerConfig { String clientSecret = "123456"; String clientName = "商城管理客户端"; - // 如果使用明文,在客户端认证的时候会自动升级加密方式(修改密码), 直接使用 bcrypt 加密避免不必要的麻烦 - // 不开玩笑,官方ISSUE: https://github.com/spring-projects/spring-authorization-server/issues/1099 + + /* + 如果使用明文,客户端认证时会自动升级加密方式,换句话说直接修改客户端密码,所以直接使用 bcrypt 加密避免不必要的麻烦 + 官方ISSUE: https://github.com/spring-projects/spring-authorization-server/issues/1099 + */ String encodeSecret = passwordEncoder().encode(clientSecret); RegisteredClient registeredMallAdminClient = registeredClientRepository.findByClientId(clientId); diff --git a/youlai-auth/src/main/java/com/youlai/auth/config/DefaultSecurityConfig.java b/youlai-auth/src/main/java/com/youlai/auth/config/DefaultSecurityConfig.java index ef07a5d3f..21e557fb3 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/config/DefaultSecurityConfig.java +++ b/youlai-auth/src/main/java/com/youlai/auth/config/DefaultSecurityConfig.java @@ -1,9 +1,5 @@ package com.youlai.auth.config; -import cn.hutool.core.collection.CollectionUtil; -import cn.hutool.core.convert.Convert; -import lombok.RequiredArgsConstructor; -import lombok.Setter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; @@ -14,17 +10,10 @@ import org.springframework.security.config.annotation.web.configuration.WebSecur import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.web.SecurityFilterChain; -import java.util.List; - @EnableWebSecurity @Configuration(proxyBeanMethods = false) public class DefaultSecurityConfig { - /** - * 读取 配置中的白名单 - */ - @Setter - private List ignoreUrls; /** * Spring Security 安全过滤器链配置 * @@ -36,12 +25,7 @@ public class DefaultSecurityConfig { SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(requestMatcherRegistry -> - { - if (CollectionUtil.isNotEmpty(ignoreUrls)) { - requestMatcherRegistry.requestMatchers(Convert.toStrArray(ignoreUrls)).permitAll(); - } - requestMatcherRegistry.anyRequest().authenticated(); - } + requestMatcherRegistry.anyRequest().authenticated() ) .csrf(AbstractHttpConfigurer::disable) .formLogin(Customizer.withDefaults()); diff --git a/youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationFailureHandler.java b/youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationFailureHandler.java index 1ce616488..a1b5f5040 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationFailureHandler.java +++ b/youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationFailureHandler.java @@ -5,7 +5,6 @@ import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.server.ServletServerHttpResponse; @@ -13,26 +12,26 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.oauth2.core.OAuth2AuthenticationException; import org.springframework.security.oauth2.core.OAuth2Error; import org.springframework.security.web.authentication.AuthenticationFailureHandler; -import org.springframework.stereotype.Component; import java.io.IOException; /** - * 认证异常处理器 + * 认证失败处理器 * * @author haoxr - * @since 2023/7/6 + * @since 3.0.0 */ @Slf4j public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { + /** + * MappingJackson2HttpMessageConverter 是 Spring 框架提供的一个 HTTP 消息转换器,用于将 HTTP 请求和响应的 JSON 数据与 Java 对象之间进行转换 + */ private final HttpMessageConverter accessTokenHttpResponseConverter = new MappingJackson2HttpMessageConverter(); @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { - log.warn(" authentication failure: ", exception); - OAuth2Error error = ((OAuth2AuthenticationException) exception).getError(); ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response); Result result = Result.failed(error.getErrorCode()); diff --git a/youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationSuccessHandler.java b/youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationSuccessHandler.java index 6fd60b4d8..d239cba83 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationSuccessHandler.java +++ b/youlai-auth/src/main/java/com/youlai/auth/handler/MyAuthenticationSuccessHandler.java @@ -25,21 +25,26 @@ import java.util.Map; * 认证成功处理器 * * @author haoxr - * @since 2023/7/3 + * @since 3.0.0 */ public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + /** + * MappingJackson2HttpMessageConverter 是 Spring 框架提供的一个 HTTP 消息转换器,用于将 HTTP 请求和响应的 JSON 数据与 Java 对象之间进行转换 + */ private final HttpMessageConverter accessTokenHttpResponseConverter = new MappingJackson2HttpMessageConverter(); private Converter> accessTokenResponseParametersConverter = new DefaultOAuth2AccessTokenResponseMapConverter(); + /** - * @param request the request which caused the successful authentication - * @param response the response + * 自定义认证成功响应数据结构 + * + * @param request the request which caused the successful authentication + * @param response the response * @param authentication the Authentication object which was created during - * the authentication process. + * the authentication process. * @throws IOException * @throws ServletException - * @see org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter#sendAccessTokenResponse */ @Override @@ -68,7 +73,7 @@ public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHand Map tokenResponseParameters = this.accessTokenResponseParametersConverter .convert(accessTokenResponse); ServletServerHttpResponse httpResponse = new ServletServerHttpResponse(response); - // 自定义认证成功响应数据结构 + this.accessTokenHttpResponseConverter.write(Result.success(tokenResponseParameters), null, httpResponse); } } diff --git a/youlai-auth/src/main/java/com/youlai/auth/userdetails/user/jackson/SysUserDeserializer.java b/youlai-auth/src/main/java/com/youlai/auth/userdetails/user/jackson/SysUserDeserializer.java index 79ad209b7..5770f39c4 100644 --- a/youlai-auth/src/main/java/com/youlai/auth/userdetails/user/jackson/SysUserDeserializer.java +++ b/youlai-auth/src/main/java/com/youlai/auth/userdetails/user/jackson/SysUserDeserializer.java @@ -38,11 +38,10 @@ class SysUserDeserializer extends JsonDeserializer { * @param jp the JsonParser * @param ctxt the DeserializationContext * @return the user - * @throws IOException if a exception during IO occurs - * @throws JsonProcessingException if an error during JSON processing occurs + * @throws IOException if a exception during IO occurs */ @Override - public SysUserDetails deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { + public SysUserDetails deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { ObjectMapper mapper = (ObjectMapper) jp.getCodec(); JsonNode jsonNode = mapper.readTree(jp); Set authorities = mapper.convertValue(jsonNode.get("authorities"), diff --git a/youlai-auth/src/test/java/com/youlai/auth/authentication/PasswordAuthenticationTests.java b/youlai-auth/src/test/java/com/youlai/auth/authentication/PasswordAuthenticationTests.java index a27d8bfb7..8dc4753d7 100644 --- a/youlai-auth/src/test/java/com/youlai/auth/authentication/PasswordAuthenticationTests.java +++ b/youlai-auth/src/test/java/com/youlai/auth/authentication/PasswordAuthenticationTests.java @@ -29,18 +29,19 @@ public class PasswordAuthenticationTests { * 测试密码模式登录 */ @Test - void testPasswordAuthentication() throws Exception { + void testPasswordLogin() throws Exception { HttpHeaders headers = new HttpHeaders(); + // 客户端ID和密钥 headers.setBasicAuth("mall-admin", "123456"); this.mvc.perform(post("/oauth2/token") - .param(OAuth2ParameterNames.GRANT_TYPE, "password") - .param(OAuth2ParameterNames.USERNAME, "admin") - .param(OAuth2ParameterNames.PASSWORD, "123456") + .param(OAuth2ParameterNames.GRANT_TYPE, "password") // 密码模式 + .param(OAuth2ParameterNames.USERNAME, "admin") // 用户名 + .param(OAuth2ParameterNames.PASSWORD, "123456") // 密码 .headers(headers)) .andDo(print()) .andExpect(status().isOk()) - .andExpect(jsonPath("$.access_token").isNotEmpty()); + .andExpect(jsonPath("$.data.access_token").isNotEmpty()); } diff --git a/youlai-system/system-boot/src/main/java/com/youlai/system/service/impl/SysMenuServiceImpl.java b/youlai-system/system-boot/src/main/java/com/youlai/system/service/impl/SysMenuServiceImpl.java index a314cd43c..5e17c8027 100644 --- a/youlai-system/system-boot/src/main/java/com/youlai/system/service/impl/SysMenuServiceImpl.java +++ b/youlai-system/system-boot/src/main/java/com/youlai/system/service/impl/SysMenuServiceImpl.java @@ -108,7 +108,7 @@ public class SysMenuServiceImpl extends ServiceImpl impl * 路由列表 */ @Override - @Cacheable(cacheNames = "system", key = "'routes'") + //@Cacheable(cacheNames = "system", key = "'routes'") public List listRoutes() { List menuList = this.baseMapper.listRoutes(); return recurRoutes(SystemConstants.ROOT_NODE_ID, menuList);