diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java index 8d21b1bde..f870ff1d8 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java @@ -117,8 +117,7 @@ public class JwtUtil { public static String getUsername(String token) { try { DecodedJWT jwt = JWT.decode(token); - LoginUser loginUser = JSONObject.parseObject(jwt.getClaim("sub").asString(), LoginUser.class); - return loginUser.getUsername(); + return jwt.getClaim("username").asString(); } catch (JWTDecodeException e) { return null; } diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java index 4dc6e8b7e..95ddab7af 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java @@ -1,5 +1,6 @@ package org.jeecg.common.util; +import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.jeecg.common.api.CommonAPI; @@ -11,14 +12,6 @@ import org.jeecg.common.exception.JeecgBoot401Exception; import org.jeecg.common.system.util.JwtUtil; import org.jeecg.common.system.vo.LoginUser; -import jakarta.servlet.http.HttpServletRequest; -import org.jeecg.config.security.JeecgRedisOAuth2AuthorizationService; -import org.springframework.data.redis.serializer.SerializationException; -import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; -import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; - -import java.util.Objects; - /** * @Author scott * @Date 2019/9/23 14:12 @@ -122,7 +115,7 @@ public class TokenUtils { throw new JeecgBoot401Exception("账号已被锁定,请联系管理员!"); } // 校验token是否超时失效 & 或者账号密码是否错误 - if (!jwtTokenRefresh(token, username, user.getPassword())) { + if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) { throw new JeecgBoot401Exception(CommonConstant.TOKEN_IS_INVALID_MSG); } return true; @@ -151,15 +144,6 @@ public class TokenUtils { return false; } - private static boolean jwtTokenRefresh(String token, String userName, String passWord) { - JeecgRedisOAuth2AuthorizationService authRedis = SpringContextUtils.getBean(JeecgRedisOAuth2AuthorizationService.class); - OAuth2Authorization authorization = authRedis.findByToken(token, OAuth2TokenType.ACCESS_TOKEN); - if (Objects.nonNull(authorization) && JwtUtil.verify(token, userName, passWord)) { - return true; - } - return false; - } - /** * 获取登录用户 * diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/CopyTokenFilter.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/CopyTokenFilter.java index e3fa6fd63..de18fbeb0 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/CopyTokenFilter.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/CopyTokenFilter.java @@ -25,12 +25,18 @@ public class CopyTokenFilter extends OncePerRequestFilter { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 以下为undertow定制代码,如切换其它servlet容器,需要同步更换 HttpServletRequestImpl undertowRequest = (HttpServletRequestImpl) request; - String bearerToken = request.getParameter("token"); - String headerBearerToken = request.getHeader("X-Access-Token"); - if (StringUtils.hasText(bearerToken)) { - undertowRequest.getExchange().getRequestHeaders().add(new HttpString("Authorization"), "bearer " + bearerToken); - } else if (StringUtils.hasText(headerBearerToken)) { - undertowRequest.getExchange().getRequestHeaders().add(new HttpString("Authorization"), "bearer " + headerBearerToken); + String token = request.getHeader("Authorization"); + if (StringUtils.hasText(token)) { + undertowRequest.getExchange().getRequestHeaders().remove("Authorization"); + undertowRequest.getExchange().getRequestHeaders().add(new HttpString("Authorization"), "bearer " + token); + } else { + String bearerToken = request.getParameter("token"); + String headerBearerToken = request.getHeader("X-Access-Token"); + if (StringUtils.hasText(bearerToken)) { + undertowRequest.getExchange().getRequestHeaders().add(new HttpString("Authorization"), "bearer " + bearerToken); + } else if (StringUtils.hasText(headerBearerToken)) { + undertowRequest.getExchange().getRequestHeaders().add(new HttpString("Authorization"), "bearer " + headerBearerToken); + } } filterChain.doFilter(undertowRequest, response); } diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/JeecgAuthenticationConvert.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/JeecgAuthenticationConvert.java new file mode 100644 index 000000000..d7c3c2138 --- /dev/null +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/JeecgAuthenticationConvert.java @@ -0,0 +1,32 @@ +package org.jeecg.config.security; + +import lombok.RequiredArgsConstructor; +import org.jeecg.common.api.CommonAPI; +import org.jeecg.common.system.vo.LoginUser; +import org.springframework.core.convert.converter.Converter; +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; + +/** + * token只存储用户名与过期时间 + * 这里通过取用户名转全量用户信息存储到Security中 + * @author eightmonth@qq.com + * @date 2024/7/15 11:05 + */ +@Component +@RequiredArgsConstructor +public class JeecgAuthenticationConvert implements Converter { + + private final CommonAPI commonAPI; + + @Override + public AbstractAuthenticationToken convert(Jwt source) { + String username = source.getClaims().get("username").toString(); + LoginUser loginUser = commonAPI.getUserByName(username); + return new UsernamePasswordAuthenticationToken(loginUser, null, new ArrayList<>()); + } +} diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/JeecgOAuth2AccessTokenGenerator.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/JeecgOAuth2AccessTokenGenerator.java new file mode 100644 index 000000000..00960db8f --- /dev/null +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/JeecgOAuth2AccessTokenGenerator.java @@ -0,0 +1,135 @@ +package org.jeecg.config.security; + +import org.jeecg.common.system.util.JwtUtil; +import org.springframework.lang.Nullable; +import org.springframework.security.oauth2.core.ClaimAccessor; +import org.springframework.security.oauth2.core.OAuth2AccessToken; +import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; +import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm; +import org.springframework.security.oauth2.jwt.JwsHeader; +import org.springframework.security.oauth2.jwt.JwtClaimsSet; +import org.springframework.security.oauth2.jwt.JwtEncoder; +import org.springframework.security.oauth2.jwt.JwtEncoderParameters; +import org.springframework.security.oauth2.server.authorization.OAuth2TokenType; +import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationGrantAuthenticationToken; +import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; +import org.springframework.security.oauth2.server.authorization.token.*; +import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; + +import java.time.Duration; +import java.time.Instant; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalUnit; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * @author eightmonth@qq.com + * @date 2024/7/11 17:10 + */ +public class JeecgOAuth2AccessTokenGenerator implements OAuth2TokenGenerator { + private final JwtEncoder jwtEncoder; + + private OAuth2TokenCustomizer accessTokenCustomizer; + + public JeecgOAuth2AccessTokenGenerator(JwtEncoder jwtEncoder) { + this.jwtEncoder = jwtEncoder; + } + + @Nullable + @Override + public OAuth2AccessToken generate(OAuth2TokenContext context) { + if (!OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) { + return null; + } + + String issuer = null; + if (context.getAuthorizationServerContext() != null) { + issuer = context.getAuthorizationServerContext().getIssuer(); + } + RegisteredClient registeredClient = context.getRegisteredClient(); + + Instant issuedAt = Instant.now(); + Instant expiresAt = issuedAt.plusMillis(JwtUtil.EXPIRE_TIME); + + OAuth2TokenClaimsSet.Builder claimsBuilder = OAuth2TokenClaimsSet.builder(); + if (StringUtils.hasText(issuer)) { + claimsBuilder.issuer(issuer); + } + claimsBuilder + .subject(context.getPrincipal().getName()) + .audience(Collections.singletonList(registeredClient.getClientId())) + .issuedAt(issuedAt) + .expiresAt(expiresAt) + .notBefore(issuedAt) + .id(UUID.randomUUID().toString()); + if (!CollectionUtils.isEmpty(context.getAuthorizedScopes())) { + claimsBuilder.claim(OAuth2ParameterNames.SCOPE, context.getAuthorizedScopes()); + } + + if (this.accessTokenCustomizer != null) { + OAuth2TokenClaimsContext.Builder accessTokenContextBuilder = OAuth2TokenClaimsContext.with(claimsBuilder) + .registeredClient(context.getRegisteredClient()) + .principal(context.getPrincipal()) + .authorizationServerContext(context.getAuthorizationServerContext()) + .authorizedScopes(context.getAuthorizedScopes()) + .tokenType(context.getTokenType()) + .authorizationGrantType(context.getAuthorizationGrantType()); + if (context.getAuthorization() != null) { + accessTokenContextBuilder.authorization(context.getAuthorization()); + } + if (context.getAuthorizationGrant() != null) { + accessTokenContextBuilder.authorizationGrant(context.getAuthorizationGrant()); + } + + OAuth2TokenClaimsContext accessTokenContext = accessTokenContextBuilder.build(); + this.accessTokenCustomizer.customize(accessTokenContext); + } + + + OAuth2TokenClaimsSet accessTokenClaimsSet = claimsBuilder.build(); + OAuth2AuthorizationGrantAuthenticationToken oAuth2ResourceOwnerBaseAuthenticationToken = context.getAuthorizationGrant(); + String username = (String) oAuth2ResourceOwnerBaseAuthenticationToken.getAdditionalParameters().get("username"); + String tokenValue = jwtEncoder.encode(JwtEncoderParameters.from(JwsHeader.with(SignatureAlgorithm.ES256).keyId("jeecg").build(), + JwtClaimsSet.builder().claim("username", username).expiresAt(expiresAt).build())).getTokenValue(); + + //此处可以做改造将tokenValue随机数换成用户信息,方便后续多系统token互通认证(通过解密token得到username) + return new OAuth2AccessTokenClaims(OAuth2AccessToken.TokenType.BEARER, tokenValue, + accessTokenClaimsSet.getIssuedAt(), accessTokenClaimsSet.getExpiresAt(), context.getAuthorizedScopes(), + accessTokenClaimsSet.getClaims()); + } + + /** + * Sets the {@link OAuth2TokenCustomizer} that customizes the + * {@link OAuth2TokenClaimsContext#getClaims() claims} for the + * {@link OAuth2AccessToken}. + * @param accessTokenCustomizer the {@link OAuth2TokenCustomizer} that customizes the + * claims for the {@code OAuth2AccessToken} + */ + public void setAccessTokenCustomizer(OAuth2TokenCustomizer accessTokenCustomizer) { + Assert.notNull(accessTokenCustomizer, "accessTokenCustomizer cannot be null"); + this.accessTokenCustomizer = accessTokenCustomizer; + } + + private static final class OAuth2AccessTokenClaims extends OAuth2AccessToken implements ClaimAccessor { + + private final Map claims; + + private OAuth2AccessTokenClaims(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt, + Set scopes, Map claims) { + super(tokenType, tokenValue, issuedAt, expiresAt, scopes); + this.claims = claims; + } + + @Override + public Map getClaims() { + return this.claims; + } + + } +} diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/RedisTokenValidationFilter.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/RedisTokenValidationFilter.java index 96daa9f28..e6e57a6c2 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/RedisTokenValidationFilter.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/RedisTokenValidationFilter.java @@ -24,7 +24,7 @@ import java.util.Objects; * @author eightmonth@qq.com * @date 2024/3/7 17:30 */ -@Component +//@Component @AllArgsConstructor public class RedisTokenValidationFilter extends OncePerRequestFilter { private OAuth2AuthorizationService authorizationService; diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/SecurityConfig.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/SecurityConfig.java index a2ae719a6..d2ef0eada 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/SecurityConfig.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/SecurityConfig.java @@ -1,11 +1,13 @@ package org.jeecg.config.security; +import com.nimbusds.jose.jwk.Curve; +import com.nimbusds.jose.jwk.ECKey; import com.nimbusds.jose.jwk.JWKSet; -import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.source.ImmutableJWKSet; import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.proc.SecurityContext; import lombok.AllArgsConstructor; +import lombok.SneakyThrows; import org.jeecg.config.security.app.AppGrantAuthenticationConvert; import org.jeecg.config.security.app.AppGrantAuthenticationProvider; import org.jeecg.config.security.password.PasswordGrantAuthenticationConvert; @@ -38,8 +40,6 @@ import org.springframework.security.oauth2.server.authorization.settings.Authori import org.springframework.security.oauth2.server.authorization.token.*; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; -import org.springframework.security.web.header.writers.frameoptions.RegExpAllowFromStrategy; -import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher; import org.springframework.web.cors.CorsConfiguration; @@ -47,10 +47,9 @@ import org.springframework.web.cors.CorsConfiguration; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.SecureRandom; -import java.security.interfaces.RSAPrivateKey; -import java.security.interfaces.RSAPublicKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.ECPublicKey; import java.util.Arrays; -import java.util.List; /** * spring authorization server核心配置 @@ -65,6 +64,7 @@ public class SecurityConfig { private JdbcTemplate jdbcTemplate; private OAuth2AuthorizationService authorizationService; + private JeecgAuthenticationConvert jeecgAuthenticationConvert; @Bean @Order(1) @@ -90,10 +90,7 @@ public class SecurityConfig { new LoginUrlAuthenticationEntryPoint("/sys/login"), new MediaTypeRequestMatcher(MediaType.TEXT_HTML) ) - ) - // 使用jwt处理接收到的access token - .oauth2ResourceServer(oauth2ResourceServer -> - oauth2ResourceServer.jwt(Customizer.withDefaults())); + ); return http.build(); } @@ -176,7 +173,7 @@ public class SecurityConfig { return config; })) .csrf(AbstractHttpConfigurer::disable) - .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())); + .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jeecgAuthenticationConvert))); return http.build(); } @@ -193,16 +190,23 @@ public class SecurityConfig { * JWK详细见:https://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key-41 */ @Bean + @SneakyThrows public JWKSource jwkSource() { - KeyPair keyPair = generateRsaKey(); - RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); - RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); - RSAKey rsaKey = new RSAKey.Builder(publicKey) + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); + // 如果不设置secureRandom,会存在一个问题,当应用重启后,原有的token将会全部失效,因为重启的keyPair与之前已经不同 + SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); + // 重要!生产环境需要修改! + secureRandom.setSeed("jeecg".getBytes()); + keyPairGenerator.initialize(256, secureRandom); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic(); + ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate(); + + ECKey jwk = new ECKey.Builder(Curve.P_256, publicKey) .privateKey(privateKey) - // 重要!生产环境需要修改! .keyID("jeecg") .build(); - JWKSet jwkSet = new JWKSet(rsaKey); + JWKSet jwkSet = new JWKSet(jwk); return new ImmutableJWKSet<>(jwkSet); } @@ -211,28 +215,6 @@ public class SecurityConfig { return NoOpPasswordEncoder.getInstance(); } - /** - *生成RSA密钥对,给上面jwkSource() 方法的提供密钥对 - */ - private static KeyPair generateRsaKey() { - KeyPair keyPair; - try { - KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); - - // 生产环境不应该设置secureRandom,seed如果被泄露,jwt容易被伪造 - // 如果不设置secureRandom,会存在一个问题,当应用重启后,原有的token将会全部失效,因为重启的keyPair与之前已经不同 - SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); - // 重要!生产环境需要修改! - secureRandom.setSeed("jeecg".getBytes()); - keyPairGenerator.initialize(2048, secureRandom); - keyPair = keyPairGenerator.generateKeyPair(); - } - catch (Exception ex) { - throw new IllegalStateException(ex); - } - return keyPair; - } - /** * 配置jwt解析器 */ @@ -241,14 +223,6 @@ public class SecurityConfig { return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); } - /** - *配置认证服务器请求地址 - */ - @Bean - public AuthorizationServerSettings authorizationServerSettings() { - return AuthorizationServerSettings.builder().tokenEndpoint("/sys/login").build(); - } - /** *配置token生成器 */ @@ -258,7 +232,9 @@ public class SecurityConfig { OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator(); OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator(); return new DelegatingOAuth2TokenGenerator( - jwtGenerator, accessTokenGenerator, refreshTokenGenerator); + new JeecgOAuth2AccessTokenGenerator(new NimbusJwtEncoder(jwkSource())), + new OAuth2RefreshTokenGenerator() + ); } } diff --git a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/self/SelfAuthenticationProvider.java b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/self/SelfAuthenticationProvider.java index 06b2f95c8..778128ab3 100644 --- a/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/self/SelfAuthenticationProvider.java +++ b/jeecg-boot/jeecg-boot-base-core/src/main/java/org/jeecg/config/security/self/SelfAuthenticationProvider.java @@ -3,6 +3,7 @@ package org.jeecg.config.security.self; import com.alibaba.fastjson.JSONObject; import org.jeecg.common.api.CommonAPI; import org.jeecg.common.constant.CommonConstant; +import org.jeecg.common.exception.JeecgBoot401Exception; import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.SysDepartModel; @@ -80,19 +81,13 @@ public class SelfAuthenticationProvider implements AuthenticationProvider { OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient(passwordGrantAuthenticationToken); RegisteredClient registeredClient = clientPrincipal.getRegisteredClient(); - if (!registeredClient.getAuthorizationGrantTypes().contains(authorizationGrantType)) { - Map map = new HashMap<>(); - map.put("message", "非法登录"); - return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,"fdsafas", Instant.now(), Instant.now().plusNanos(1)), null, map); - } - // 通过用户名获取用户信息 - LoginUser loginUser = commonAPI.getUserByName(username); +// LoginUser loginUser = commonAPI.getUserByName(username); // 检查用户可行性 - checkUserIsEffective(loginUser); +// checkUserIsEffective(loginUser); //由于在上面已验证过用户名、密码,现在构建一个已认证的对象UsernamePasswordAuthenticationToken - UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken.authenticated(loginUser,clientPrincipal,new ArrayList<>()); + UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken.authenticated(username,clientPrincipal,new ArrayList<>()); DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder() .registeredClient(registeredClient) @@ -101,90 +96,87 @@ public class SelfAuthenticationProvider implements AuthenticationProvider { .authorizedScopes(requestScopeSet) .authorizationGrant(passwordGrantAuthenticationToken); - OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient) - .principalName(clientPrincipal.getName()) - .authorizedScopes(requestScopeSet) - .attribute(Principal.class.getName(), username) - .authorizationGrantType(authorizationGrantType); +// OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient) +// .principalName(clientPrincipal.getName()) +// .authorizedScopes(requestScopeSet) +// .attribute(Principal.class.getName(), username) +// .authorizationGrantType(authorizationGrantType); // ----- Access token ----- OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build(); OAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext); if (generatedAccessToken == null) { - Map map = new HashMap<>(); - map.put("message", "无法生成刷新token,请联系管理员。"); - return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,"fdsafas", Instant.now(), Instant.now().plusNanos(1)), null, map); - + throw new JeecgBoot401Exception("无法生成刷新token,请联系管理员。"); } OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(), generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes()); - if (generatedAccessToken instanceof ClaimAccessor) { - authorizationBuilder.token(accessToken, (metadata) -> { - metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims()); - }); - } else { - authorizationBuilder.accessToken(accessToken); - } +// if (generatedAccessToken instanceof ClaimAccessor) { +// authorizationBuilder.token(accessToken, (metadata) -> { +// metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims()); +// }); +// } else { +// authorizationBuilder.accessToken(accessToken); +// } // ----- Refresh token ----- - OAuth2RefreshToken refreshToken = null; - if (registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN) && - // 不向公共客户端颁发刷新令牌 - !clientPrincipal.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) { +// OAuth2RefreshToken refreshToken = null; +// if (registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN) && +// // 不向公共客户端颁发刷新令牌 +// !clientPrincipal.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) { +// +// tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.REFRESH_TOKEN).build(); +// OAuth2Token generatedRefreshToken = this.tokenGenerator.generate(tokenContext); +// if (!(generatedRefreshToken instanceof OAuth2RefreshToken)) { +// Map map = new HashMap<>(); +// map.put("message", "无法生成刷新token,请联系管理员。"); +// return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,"fdsafas", Instant.now(), Instant.now().plusNanos(1)), null, map); +// } +// +// refreshToken = (OAuth2RefreshToken) generatedRefreshToken; +// authorizationBuilder.refreshToken(refreshToken); +// } - tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.REFRESH_TOKEN).build(); - OAuth2Token generatedRefreshToken = this.tokenGenerator.generate(tokenContext); - if (!(generatedRefreshToken instanceof OAuth2RefreshToken)) { - Map map = new HashMap<>(); - map.put("message", "无法生成刷新token,请联系管理员。"); - return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,"fdsafas", Instant.now(), Instant.now().plusNanos(1)), null, map); - } +// OAuth2Authorization authorization = authorizationBuilder.build(); +// +// // 保存认证信息至redis +// authorizationService.save(authorization); - refreshToken = (OAuth2RefreshToken) generatedRefreshToken; - authorizationBuilder.refreshToken(refreshToken); - } - - OAuth2Authorization authorization = authorizationBuilder.build(); - - // 保存认证信息至redis - authorizationService.save(authorization); - - JSONObject addition = new JSONObject(new LinkedHashMap<>()); - addition.put("token", accessToken.getTokenValue()); - // 设置租户 - JSONObject jsonObject = commonAPI.setLoginTenant(username); - addition.putAll(jsonObject.getInnerMap()); - - // 设置登录用户信息 - addition.put("userInfo", loginUser); - addition.put("sysAllDictItems", commonAPI.queryAllDictItems()); - - List departs = commonAPI.queryUserDeparts(loginUser.getId()); - addition.put("departs", departs); - if (departs == null || departs.size() == 0) { - addition.put("multi_depart", 0); - } else if (departs.size() == 1) { - commonAPI.updateUserDepart(username, departs.get(0).getOrgCode(),null); - addition.put("multi_depart", 1); - } else { - //查询当前是否有登录部门 - if(oConvertUtils.isEmpty(loginUser.getOrgCode())){ - commonAPI.updateUserDepart(username, departs.get(0).getOrgCode(),null); - } - addition.put("multi_depart", 2); - } +// JSONObject addition = new JSONObject(new LinkedHashMap<>()); +// addition.put("token", accessToken.getTokenValue()); +// // 设置租户 +// JSONObject jsonObject = commonAPI.setLoginTenant(username); +// addition.putAll(jsonObject.getInnerMap()); +// +// // 设置登录用户信息 +// addition.put("userInfo", loginUser); +// addition.put("sysAllDictItems", commonAPI.queryAllDictItems()); +// +// List departs = commonAPI.queryUserDeparts(loginUser.getId()); +// addition.put("departs", departs); +// if (departs == null || departs.size() == 0) { +// addition.put("multi_depart", 0); +// } else if (departs.size() == 1) { +// commonAPI.updateUserDepart(username, departs.get(0).getOrgCode(),null); +// addition.put("multi_depart", 1); +// } else { +// //查询当前是否有登录部门 +// if(oConvertUtils.isEmpty(loginUser.getOrgCode())){ +// commonAPI.updateUserDepart(username, departs.get(0).getOrgCode(),null); +// } +// addition.put("multi_depart", 2); +// } // 兼容原有shiro登录结果处理 - Map map = new HashMap<>(); - map.put("result", addition); - map.put("code", 200); - map.put("success", true); - map.put("timestamp", System.currentTimeMillis()); +// Map map = new HashMap<>(); +// map.put("result", addition); +// map.put("code", 200); +// map.put("success", true); +// map.put("timestamp", System.currentTimeMillis()); // 返回access_token、refresh_token以及其它信息给到前端 - return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken, refreshToken, map); + return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken); } @Override diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java index 51679908f..b4e550e34 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java @@ -89,9 +89,8 @@ public class LoginController { * @param sysLoginModel * @return */ - @Deprecated -// @Operation(summary = "登录接口") -// @RequestMapping(value = "/login", method = RequestMethod.POST) + @Operation(summary = "登录接口") + @RequestMapping(value = "/login", method = RequestMethod.POST) public Result login(@RequestBody SysLoginModel sysLoginModel, HttpServletRequest request){ Result result = new Result(); String username = sysLoginModel.getUsername();