-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/springboot3_sas' into springboot…
…3_sas
- Loading branch information
Showing
16 changed files
with
8,507 additions
and
10,888 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
...cg-boot-base-core/src/main/java/org/jeecg/config/security/JeecgAuthenticationConvert.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 [email protected] | ||
* @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<>()); | ||
} | ||
} |
135 changes: 135 additions & 0 deletions
135
...ot-base-core/src/main/java/org/jeecg/config/security/JeecgOAuth2AccessTokenGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 [email protected] | ||
* @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; | ||
} | ||
|
||
} | ||
} |
Oops, something went wrong.