缩短token长度,适配主分支前端页面登录

pull/6899/head
EightMonth 2024-07-15 17:11:05 +08:00
parent 7d8b653d6e
commit 0e762b4157
9 changed files with 276 additions and 153 deletions

View File

@ -117,8 +117,7 @@ public class JwtUtil {
public static String getUsername(String token) { public static String getUsername(String token) {
try { try {
DecodedJWT jwt = JWT.decode(token); DecodedJWT jwt = JWT.decode(token);
LoginUser loginUser = JSONObject.parseObject(jwt.getClaim("sub").asString(), LoginUser.class); return jwt.getClaim("username").asString();
return loginUser.getUsername();
} catch (JWTDecodeException e) { } catch (JWTDecodeException e) {
return null; return null;
} }

View File

@ -1,5 +1,6 @@
package org.jeecg.common.util; package org.jeecg.common.util;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.CommonAPI; 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.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser; 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 * @Author scott
* @Date 2019/9/23 14:12 * @Date 2019/9/23 14:12
@ -122,7 +115,7 @@ public class TokenUtils {
throw new JeecgBoot401Exception("账号已被锁定,请联系管理员!"); throw new JeecgBoot401Exception("账号已被锁定,请联系管理员!");
} }
// 校验token是否超时失效 & 或者账号密码是否错误 // 校验token是否超时失效 & 或者账号密码是否错误
if (!jwtTokenRefresh(token, username, user.getPassword())) { if (!jwtTokenRefresh(token, username, user.getPassword(), redisUtil)) {
throw new JeecgBoot401Exception(CommonConstant.TOKEN_IS_INVALID_MSG); throw new JeecgBoot401Exception(CommonConstant.TOKEN_IS_INVALID_MSG);
} }
return true; return true;
@ -151,15 +144,6 @@ public class TokenUtils {
return false; 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;
}
/** /**
* *
* *

View File

@ -25,12 +25,18 @@ public class CopyTokenFilter extends OncePerRequestFilter {
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 以下为undertow定制代码如切换其它servlet容器需要同步更换 // 以下为undertow定制代码如切换其它servlet容器需要同步更换
HttpServletRequestImpl undertowRequest = (HttpServletRequestImpl) request; HttpServletRequestImpl undertowRequest = (HttpServletRequestImpl) request;
String bearerToken = request.getParameter("token"); String token = request.getHeader("Authorization");
String headerBearerToken = request.getHeader("X-Access-Token"); if (StringUtils.hasText(token)) {
if (StringUtils.hasText(bearerToken)) { undertowRequest.getExchange().getRequestHeaders().remove("Authorization");
undertowRequest.getExchange().getRequestHeaders().add(new HttpString("Authorization"), "bearer " + bearerToken); undertowRequest.getExchange().getRequestHeaders().add(new HttpString("Authorization"), "bearer " + token);
} else if (StringUtils.hasText(headerBearerToken)) { } else {
undertowRequest.getExchange().getRequestHeaders().add(new HttpString("Authorization"), "bearer " + headerBearerToken); 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); filterChain.doFilter(undertowRequest, response);
} }

View File

@ -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<Jwt, AbstractAuthenticationToken> {
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<>());
}
}

View File

@ -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<OAuth2AccessToken> {
private final JwtEncoder jwtEncoder;
private OAuth2TokenCustomizer<OAuth2TokenClaimsContext> 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<OAuth2TokenClaimsContext> accessTokenCustomizer) {
Assert.notNull(accessTokenCustomizer, "accessTokenCustomizer cannot be null");
this.accessTokenCustomizer = accessTokenCustomizer;
}
private static final class OAuth2AccessTokenClaims extends OAuth2AccessToken implements ClaimAccessor {
private final Map<String, Object> claims;
private OAuth2AccessTokenClaims(TokenType tokenType, String tokenValue, Instant issuedAt, Instant expiresAt,
Set<String> scopes, Map<String, Object> claims) {
super(tokenType, tokenValue, issuedAt, expiresAt, scopes);
this.claims = claims;
}
@Override
public Map<String, Object> getClaims() {
return this.claims;
}
}
}

View File

@ -24,7 +24,7 @@ import java.util.Objects;
* @author eightmonth@qq.com * @author eightmonth@qq.com
* @date 2024/3/7 17:30 * @date 2024/3/7 17:30
*/ */
@Component //@Component
@AllArgsConstructor @AllArgsConstructor
public class RedisTokenValidationFilter extends OncePerRequestFilter { public class RedisTokenValidationFilter extends OncePerRequestFilter {
private OAuth2AuthorizationService authorizationService; private OAuth2AuthorizationService authorizationService;

View File

@ -1,11 +1,13 @@
package org.jeecg.config.security; 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.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet; import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext; import com.nimbusds.jose.proc.SecurityContext;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.jeecg.config.security.app.AppGrantAuthenticationConvert; import org.jeecg.config.security.app.AppGrantAuthenticationConvert;
import org.jeecg.config.security.app.AppGrantAuthenticationProvider; import org.jeecg.config.security.app.AppGrantAuthenticationProvider;
import org.jeecg.config.security.password.PasswordGrantAuthenticationConvert; 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.oauth2.server.authorization.token.*;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; 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.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher; import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfiguration;
@ -47,10 +47,9 @@ import org.springframework.web.cors.CorsConfiguration;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.KeyPairGenerator; import java.security.KeyPairGenerator;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.ECPrivateKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.ECPublicKey;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
/** /**
* spring authorization server * spring authorization server
@ -65,6 +64,7 @@ public class SecurityConfig {
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
private OAuth2AuthorizationService authorizationService; private OAuth2AuthorizationService authorizationService;
private JeecgAuthenticationConvert jeecgAuthenticationConvert;
@Bean @Bean
@Order(1) @Order(1)
@ -90,10 +90,7 @@ public class SecurityConfig {
new LoginUrlAuthenticationEntryPoint("/sys/login"), new LoginUrlAuthenticationEntryPoint("/sys/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML) new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
) )
) );
// 使用jwt处理接收到的access token
.oauth2ResourceServer(oauth2ResourceServer ->
oauth2ResourceServer.jwt(Customizer.withDefaults()));
return http.build(); return http.build();
} }
@ -176,7 +173,7 @@ public class SecurityConfig {
return config; return config;
})) }))
.csrf(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable)
.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults())); .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jeecgAuthenticationConvert)));
return http.build(); return http.build();
} }
@ -193,16 +190,23 @@ public class SecurityConfig {
* JWKhttps://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key-41 * JWKhttps://datatracker.ietf.org/doc/html/draft-ietf-jose-json-web-key-41
*/ */
@Bean @Bean
@SneakyThrows
public JWKSource<SecurityContext> jwkSource() { public JWKSource<SecurityContext> jwkSource() {
KeyPair keyPair = generateRsaKey(); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 如果不设置secureRandom会存在一个问题当应用重启后原有的token将会全部失效因为重启的keyPair与之前已经不同
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
RSAKey rsaKey = new RSAKey.Builder(publicKey) // 重要!生产环境需要修改!
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) .privateKey(privateKey)
// 重要!生产环境需要修改!
.keyID("jeecg") .keyID("jeecg")
.build(); .build();
JWKSet jwkSet = new JWKSet(rsaKey); JWKSet jwkSet = new JWKSet(jwk);
return new ImmutableJWKSet<>(jwkSet); return new ImmutableJWKSet<>(jwkSet);
} }
@ -211,28 +215,6 @@ public class SecurityConfig {
return NoOpPasswordEncoder.getInstance(); return NoOpPasswordEncoder.getInstance();
} }
/**
*RSAjwkSource()
*/
private static KeyPair generateRsaKey() {
KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
// 生产环境不应该设置secureRandomseed如果被泄露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 * jwt
*/ */
@ -241,14 +223,6 @@ public class SecurityConfig {
return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
} }
/**
*
*/
@Bean
public AuthorizationServerSettings authorizationServerSettings() {
return AuthorizationServerSettings.builder().tokenEndpoint("/sys/login").build();
}
/** /**
*token *token
*/ */
@ -258,7 +232,9 @@ public class SecurityConfig {
OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator(); OAuth2AccessTokenGenerator accessTokenGenerator = new OAuth2AccessTokenGenerator();
OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator(); OAuth2RefreshTokenGenerator refreshTokenGenerator = new OAuth2RefreshTokenGenerator();
return new DelegatingOAuth2TokenGenerator( return new DelegatingOAuth2TokenGenerator(
jwtGenerator, accessTokenGenerator, refreshTokenGenerator); new JeecgOAuth2AccessTokenGenerator(new NimbusJwtEncoder(jwkSource())),
new OAuth2RefreshTokenGenerator()
);
} }
} }

View File

@ -3,6 +3,7 @@ package org.jeecg.config.security.self;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import org.jeecg.common.api.CommonAPI; import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.constant.CommonConstant; import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBoot401Exception;
import org.jeecg.common.exception.JeecgBootException; import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser; import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.system.vo.SysDepartModel; import org.jeecg.common.system.vo.SysDepartModel;
@ -80,19 +81,13 @@ public class SelfAuthenticationProvider implements AuthenticationProvider {
OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient(passwordGrantAuthenticationToken); OAuth2ClientAuthenticationToken clientPrincipal = getAuthenticatedClientElseThrowInvalidClient(passwordGrantAuthenticationToken);
RegisteredClient registeredClient = clientPrincipal.getRegisteredClient(); RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();
if (!registeredClient.getAuthorizationGrantTypes().contains(authorizationGrantType)) {
Map<String, Object> 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 = UsernamePasswordAuthenticationToken.authenticated(loginUser,clientPrincipal,new ArrayList<>()); UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken.authenticated(username,clientPrincipal,new ArrayList<>());
DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder() DefaultOAuth2TokenContext.Builder tokenContextBuilder = DefaultOAuth2TokenContext.builder()
.registeredClient(registeredClient) .registeredClient(registeredClient)
@ -101,90 +96,87 @@ public class SelfAuthenticationProvider implements AuthenticationProvider {
.authorizedScopes(requestScopeSet) .authorizedScopes(requestScopeSet)
.authorizationGrant(passwordGrantAuthenticationToken); .authorizationGrant(passwordGrantAuthenticationToken);
OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient) // OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient)
.principalName(clientPrincipal.getName()) // .principalName(clientPrincipal.getName())
.authorizedScopes(requestScopeSet) // .authorizedScopes(requestScopeSet)
.attribute(Principal.class.getName(), username) // .attribute(Principal.class.getName(), username)
.authorizationGrantType(authorizationGrantType); // .authorizationGrantType(authorizationGrantType);
// ----- Access token ----- // ----- Access token -----
OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build(); OAuth2TokenContext tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.ACCESS_TOKEN).build();
OAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext); OAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext);
if (generatedAccessToken == null) { if (generatedAccessToken == null) {
Map<String, Object> map = new HashMap<>(); throw new JeecgBoot401Exception("无法生成刷新token请联系管理员。");
map.put("message", "无法生成刷新token请联系管理员。");
return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,"fdsafas", Instant.now(), Instant.now().plusNanos(1)), null, map);
} }
OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(), generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes()); generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());
if (generatedAccessToken instanceof ClaimAccessor) { // if (generatedAccessToken instanceof ClaimAccessor) {
authorizationBuilder.token(accessToken, (metadata) -> { // authorizationBuilder.token(accessToken, (metadata) -> {
metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims()); // metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims());
}); // });
} else { // } else {
authorizationBuilder.accessToken(accessToken); // authorizationBuilder.accessToken(accessToken);
} // }
// ----- Refresh token ----- // ----- Refresh token -----
OAuth2RefreshToken refreshToken = null; // OAuth2RefreshToken refreshToken = null;
if (registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN) && // if (registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.REFRESH_TOKEN) &&
// 不向公共客户端颁发刷新令牌 // // 不向公共客户端颁发刷新令牌
!clientPrincipal.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) { // !clientPrincipal.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.NONE)) {
//
// tokenContext = tokenContextBuilder.tokenType(OAuth2TokenType.REFRESH_TOKEN).build();
// OAuth2Token generatedRefreshToken = this.tokenGenerator.generate(tokenContext);
// if (!(generatedRefreshToken instanceof OAuth2RefreshToken)) {
// Map<String, Object> 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(); // OAuth2Authorization authorization = authorizationBuilder.build();
OAuth2Token generatedRefreshToken = this.tokenGenerator.generate(tokenContext); //
if (!(generatedRefreshToken instanceof OAuth2RefreshToken)) { // // 保存认证信息至redis
Map<String, Object> map = new HashMap<>(); // authorizationService.save(authorization);
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; // JSONObject addition = new JSONObject(new LinkedHashMap<>());
authorizationBuilder.refreshToken(refreshToken); // addition.put("token", accessToken.getTokenValue());
} // // 设置租户
// JSONObject jsonObject = commonAPI.setLoginTenant(username);
OAuth2Authorization authorization = authorizationBuilder.build(); // addition.putAll(jsonObject.getInnerMap());
//
// 保存认证信息至redis // // 设置登录用户信息
authorizationService.save(authorization); // addition.put("userInfo", loginUser);
// addition.put("sysAllDictItems", commonAPI.queryAllDictItems());
JSONObject addition = new JSONObject(new LinkedHashMap<>()); //
addition.put("token", accessToken.getTokenValue()); // List<SysDepartModel> departs = commonAPI.queryUserDeparts(loginUser.getId());
// 设置租户 // addition.put("departs", departs);
JSONObject jsonObject = commonAPI.setLoginTenant(username); // if (departs == null || departs.size() == 0) {
addition.putAll(jsonObject.getInnerMap()); // addition.put("multi_depart", 0);
// } else if (departs.size() == 1) {
// 设置登录用户信息 // commonAPI.updateUserDepart(username, departs.get(0).getOrgCode(),null);
addition.put("userInfo", loginUser); // addition.put("multi_depart", 1);
addition.put("sysAllDictItems", commonAPI.queryAllDictItems()); // } else {
// //查询当前是否有登录部门
List<SysDepartModel> departs = commonAPI.queryUserDeparts(loginUser.getId()); // if(oConvertUtils.isEmpty(loginUser.getOrgCode())){
addition.put("departs", departs); // commonAPI.updateUserDepart(username, departs.get(0).getOrgCode(),null);
if (departs == null || departs.size() == 0) { // }
addition.put("multi_depart", 0); // addition.put("multi_depart", 2);
} 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登录结果处理 // 兼容原有shiro登录结果处理
Map<String, Object> map = new HashMap<>(); // Map<String, Object> map = new HashMap<>();
map.put("result", addition); // map.put("result", addition);
map.put("code", 200); // map.put("code", 200);
map.put("success", true); // map.put("success", true);
map.put("timestamp", System.currentTimeMillis()); // map.put("timestamp", System.currentTimeMillis());
// 返回access_token、refresh_token以及其它信息给到前端 // 返回access_token、refresh_token以及其它信息给到前端
return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken, refreshToken, map); return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken);
} }
@Override @Override

View File

@ -89,9 +89,8 @@ public class LoginController {
* @param sysLoginModel * @param sysLoginModel
* @return * @return
*/ */
@Deprecated @Operation(summary = "登录接口")
// @Operation(summary = "登录接口") @RequestMapping(value = "/login", method = RequestMethod.POST)
// @RequestMapping(value = "/login", method = RequestMethod.POST)
public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel, HttpServletRequest request){ public Result<JSONObject> login(@RequestBody SysLoginModel sysLoginModel, HttpServletRequest request){
Result<JSONObject> result = new Result<JSONObject>(); Result<JSONObject> result = new Result<JSONObject>();
String username = sysLoginModel.getUsername(); String username = sysLoginModel.getUsername();