From c77960c7776600536bf11db9557d9942812682b8 Mon Sep 17 00:00:00 2001 From: zhuyijun Date: Thu, 18 Aug 2022 22:59:07 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Ejwt=E5=A2=9E=E5=BC=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../entity/constant/ContextKeyConstant.java | 10 +++ .../common/entity/jwt/OauthClaims.java | 23 +++++ zyjblogs-gateway/pom.xml | 8 +- .../zyjblogs/gateway/filter/AuthFilter.java | 10 ++- zyjblogs-oauth/pom.xml | 6 ++ .../AuthorizationServerConfiguration.java | 10 ++- .../{TokenConfig.java => JwtTokenConfig.java} | 2 +- .../config/security/JwtTokenEnhancer.java | 39 ++++++++ .../security/OauthAuthenticationProvider.java | 19 ++++ .../security/WebSecurityConfiguration.java | 13 +++ .../server/user/po/OauthUserDetails.java | 88 ++++++++++++++++++- .../impl/OauthUserDetailsServiceImpl.java | 5 +- 12 files changed, 222 insertions(+), 11 deletions(-) create mode 100644 zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/common/entity/constant/ContextKeyConstant.java create mode 100644 zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/common/entity/jwt/OauthClaims.java rename zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/{TokenConfig.java => JwtTokenConfig.java} (97%) create mode 100644 zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/JwtTokenEnhancer.java create mode 100644 zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/OauthAuthenticationProvider.java diff --git a/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/common/entity/constant/ContextKeyConstant.java b/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/common/entity/constant/ContextKeyConstant.java new file mode 100644 index 0000000..13b545a --- /dev/null +++ b/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/common/entity/constant/ContextKeyConstant.java @@ -0,0 +1,10 @@ +package cn.zyjblogs.common.entity.constant; + +/** + * @author zhuyijun + */ +public class ContextKeyConstant { + public static final String USER_ID_KEY = "user_id"; + public static final String USERNAME_KEY = "username"; + public static final String TENANT_ID_KEY = "tenant_id"; +} diff --git a/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/common/entity/jwt/OauthClaims.java b/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/common/entity/jwt/OauthClaims.java new file mode 100644 index 0000000..d48b253 --- /dev/null +++ b/zyjblogs-common-spring-boot-starter/src/main/java/cn/zyjblogs/common/entity/jwt/OauthClaims.java @@ -0,0 +1,23 @@ +package cn.zyjblogs.common.entity.jwt; + +import io.jsonwebtoken.impl.DefaultClaims; + +/** + * @author zhuyijun + */ +public class OauthClaims extends DefaultClaims { + + public String getUserId(){ + return this.getString("user_id"); + } + public void setUserId(String userId){ + this.setValue("user_id",userId); + } + public String getUsername(){ + return this.getString("username"); + } + + public void setUsername(String username){ + this.setValue("username", username); + } +} diff --git a/zyjblogs-gateway/pom.xml b/zyjblogs-gateway/pom.xml index 67d6a1a..ec25d20 100644 --- a/zyjblogs-gateway/pom.xml +++ b/zyjblogs-gateway/pom.xml @@ -86,10 +86,10 @@ - - org.springframework.cloud - spring-cloud-starter-oauth2 - + + + + cn.zyjblogs.starter zyjblogs-common-spring-boot-starter diff --git a/zyjblogs-gateway/src/main/java/cn/zyjblogs/gateway/filter/AuthFilter.java b/zyjblogs-gateway/src/main/java/cn/zyjblogs/gateway/filter/AuthFilter.java index 3d02159..2e56fc9 100644 --- a/zyjblogs-gateway/src/main/java/cn/zyjblogs/gateway/filter/AuthFilter.java +++ b/zyjblogs-gateway/src/main/java/cn/zyjblogs/gateway/filter/AuthFilter.java @@ -1,11 +1,17 @@ package cn.zyjblogs.gateway.filter; import cn.zyjblogs.common.entity.constant.HttpHeaderConstant; +import cn.zyjblogs.common.entity.context.BaseContextHandler; +import cn.zyjblogs.common.entity.dto.ContextDto; +import cn.zyjblogs.common.entity.jwt.OauthClaims; import cn.zyjblogs.common.entity.response.ResponseObject; import cn.zyjblogs.common.entity.response.ResponseResult; import cn.zyjblogs.common.entity.response.ResponseStatus; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwt; +import io.jsonwebtoken.Jwts; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -43,7 +49,7 @@ import java.util.List; public class AuthFilter implements GlobalFilter { private final WhiteListProperties whiteListProperties; private AntPathMatcher antPathMatcher = new AntPathMatcher(); - + private String SIGNING_KEY="zyjblogs123"; @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { @@ -98,6 +104,8 @@ public class AuthFilter implements GlobalFilter { return false; } String jwt = token.replace(HttpHeaderConstant.AUTHORIZATION_TYPE + " ", ""); + OauthClaims body = (OauthClaims) Jwts.parser().setSigningKey(SIGNING_KEY).parseClaimsJws(jwt).getBody(); + BaseContextHandler.set(ContextDto.builder().token(jwt).userId(body.getUserId()).username(body.getUsername()).build()); return true; } diff --git a/zyjblogs-oauth/pom.xml b/zyjblogs-oauth/pom.xml index 09a0588..645acac 100644 --- a/zyjblogs-oauth/pom.xml +++ b/zyjblogs-oauth/pom.xml @@ -78,6 +78,12 @@ org.springframework.boot spring-boot-starter-data-redis + + cn.zyjblogs.starter + zyjblogs-common-spring-boot-starter + ${zyjblogs.version} + compile + diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/AuthorizationServerConfiguration.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/AuthorizationServerConfiguration.java index 6758d68..6da6871 100644 --- a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/AuthorizationServerConfiguration.java +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/AuthorizationServerConfiguration.java @@ -44,6 +44,7 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu private final JwtAccessTokenConverter accessTokenConverter; private final PasswordEncoder passwordEncoder; private final DataSource dataSource; + private final JwtTokenEnhancer jwtTokenEnhancer; /** * 令牌端点的安全约束 * @@ -56,7 +57,7 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu security //允许匿名访问端点:url:/oauth/token_key .tokenKeyAccess("permitAll()") - .checkTokenAccess("permitAll()") + .checkTokenAccess("isAuthenticated()") //TODO 待处理令牌访问安全 //允许匿名访问端点:url:/oauth/check_token // .checkTokenAccess("isAuthenticated()") @@ -83,12 +84,14 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints. //密码模式 authenticationManager(authenticationManager) //授权码模式 .authorizationCodeServices(authorizationCodeServices(dataSource)) .tokenServices(tokenServices()) + .accessTokenConverter(accessTokenConverter) //允许表单认证 .allowedTokenEndpointRequestMethods(HttpMethod.POST); } @@ -107,8 +110,9 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu tokenServices.setSupportRefreshToken(true); //令牌储存策略 tokenServices.setTokenStore(tokenStore); - tokenServices.setTokenEnhancer(accessTokenConverter); - + TokenEnhancerChain enhancerChain = new TokenEnhancerChain(); + enhancerChain.setTokenEnhancers(List.of(jwtTokenEnhancer,accessTokenConverter)); + tokenServices.setTokenEnhancer(enhancerChain); //令牌默认有效期 tokenServices.setAccessTokenValiditySeconds(7200); //刷新令牌默认有效期3天 diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/TokenConfig.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/JwtTokenConfig.java similarity index 97% rename from zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/TokenConfig.java rename to zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/JwtTokenConfig.java index a2e80d3..ab706c7 100644 --- a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/TokenConfig.java +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/JwtTokenConfig.java @@ -11,7 +11,7 @@ import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; * @author zhuyijun */ @Configuration -public class TokenConfig { +public class JwtTokenConfig { private String SIGNING_KEY="zyjblogs123"; /** * 令牌存储策略 diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/JwtTokenEnhancer.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/JwtTokenEnhancer.java new file mode 100644 index 0000000..e9625d0 --- /dev/null +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/JwtTokenEnhancer.java @@ -0,0 +1,39 @@ +package cn.zyjblogs.oauth.config.security; + +import cn.zyjblogs.common.entity.constant.ContextKeyConstant; +import cn.zyjblogs.oauth.server.user.po.OauthUserDetails; +import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.provider.OAuth2Authentication; +import org.springframework.security.oauth2.provider.token.TokenEnhancer; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.Map; + +/** + * jwt内容增强器 + * @author zhuyijun + */ +@Component +public class JwtTokenEnhancer implements TokenEnhancer { + /** + * token增强 + * @param oAuth2AccessToken + * @param authentication + * @author zhuyijun + * @date 2022/8/18 下午8:51 + * @return org.springframework.security.oauth2.common.OAuth2AccessToken + */ + @Override + public OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication authentication) { + OauthUserDetails authUser = (OauthUserDetails) authentication.getPrincipal(); + final Map additionalInfo = new HashMap<>(4); + // 注意添加的额外信息,不能和已有的json对象中的key重名 + additionalInfo.put(ContextKeyConstant.USER_ID_KEY, authUser.getId()); + additionalInfo.put(ContextKeyConstant.USERNAME_KEY, authUser.getUsername()); + ((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo); + return oAuth2AccessToken; + + } +} diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/OauthAuthenticationProvider.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/OauthAuthenticationProvider.java new file mode 100644 index 0000000..9330ba1 --- /dev/null +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/OauthAuthenticationProvider.java @@ -0,0 +1,19 @@ +package cn.zyjblogs.oauth.config.security; + +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; + +/** + * @author zhuyijun + */ +//@Component("oauthAuthenticationProvider") +//public class OauthAuthenticationProvider extends DaoAuthenticationProvider { +// +// @Override +// protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { +// super.additionalAuthenticationChecks(userDetails, authentication); +// } +//} diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/WebSecurityConfiguration.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/WebSecurityConfiguration.java index c022ec7..be92bb1 100644 --- a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/WebSecurityConfiguration.java +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/WebSecurityConfiguration.java @@ -1,8 +1,11 @@ package cn.zyjblogs.oauth.config.security; +import cn.zyjblogs.oauth.server.user.service.impl.OauthUserDetailsServiceImpl; +import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @@ -19,8 +22,11 @@ import javax.sql.DataSource; @Configuration @EnableWebSecurity +@RequiredArgsConstructor public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { +// private final OauthUserDetailsServiceImpl oauthUserDetailsService; +// private final OauthAuthenticationProvider oauthAuthenticationProvider; /** * 密码编码解码 * @@ -44,6 +50,13 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { return super.authenticationManagerBean(); } +// @Override +// protected void configure(AuthenticationManagerBuilder auth) throws Exception { +// auth.authenticationProvider(oauthAuthenticationProvider) +// .userDetailsService(oauthUserDetailsService) +// .passwordEncoder(passwordEncoder()); +// } + @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/server/user/po/OauthUserDetails.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/server/user/po/OauthUserDetails.java index 57028e9..bbb8ea6 100644 --- a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/server/user/po/OauthUserDetails.java +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/server/user/po/OauthUserDetails.java @@ -11,6 +11,7 @@ import lombok.Setter; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; +import java.io.Serializable; import java.util.Collection; import java.util.Set; @@ -21,7 +22,7 @@ import java.util.Set; @AllArgsConstructor @NoArgsConstructor @Builder -public class OauthUserDetails implements UserDetails { +public class OauthUserDetails implements UserDetails, Serializable { private String id; private String username; @@ -44,6 +45,91 @@ public class OauthUserDetails implements UserDetails { private boolean accountNonLocked = true; private boolean credentialsNonExpired = true; private boolean enabled = true; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setPassword(String password) { + this.password = password; + } + + public Integer getPhone() { + return phone; + } + + public void setPhone(Integer phone) { + this.phone = phone; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getInviteUserId() { + return inviteUserId; + } + + public void setInviteUserId(String inviteUserId) { + this.inviteUserId = inviteUserId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getDeleted() { + return deleted; + } + + public void setDeleted(Integer deleted) { + this.deleted = deleted; + } + + public void setAuthorities(Collection authorities) { + this.authorities = authorities; + } + + public void setAccountNonExpired(boolean accountNonExpired) { + this.accountNonExpired = accountNonExpired; + } + + public void setAccountNonLocked(boolean accountNonLocked) { + this.accountNonLocked = accountNonLocked; + } + + public void setCredentialsNonExpired(boolean credentialsNonExpired) { + this.credentialsNonExpired = credentialsNonExpired; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + @Override public Collection getAuthorities() { return authorities; diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/server/user/service/impl/OauthUserDetailsServiceImpl.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/server/user/service/impl/OauthUserDetailsServiceImpl.java index c7a3a09..7bf227a 100644 --- a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/server/user/service/impl/OauthUserDetailsServiceImpl.java +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/server/user/service/impl/OauthUserDetailsServiceImpl.java @@ -15,7 +15,10 @@ import org.springframework.stereotype.Service; import java.util.List; -@Service +/** + * @author zhuyijun + */ +@Service("oauthUserDetailsService") @RequiredArgsConstructor public class OauthUserDetailsServiceImpl implements UserDetailsService { private final UserService userService;