新增jwt增强

This commit is contained in:
zhuyijun 2022-08-18 22:59:07 +08:00
parent 85a6e2a486
commit c77960c777
12 changed files with 222 additions and 11 deletions

View File

@ -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";
}

View File

@ -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);
}
}

View File

@ -86,10 +86,10 @@
<!-- <groupId>org.springframework.security.oauth.boot</groupId>--> <!-- <groupId>org.springframework.security.oauth.boot</groupId>-->
<!-- <artifactId>spring-security-oauth2-autoconfigure</artifactId>--> <!-- <artifactId>spring-security-oauth2-autoconfigure</artifactId>-->
<!-- </dependency>--> <!-- </dependency>-->
<dependency> <!-- <dependency>-->
<groupId>org.springframework.cloud</groupId> <!-- <groupId>org.springframework.cloud</groupId>-->
<artifactId>spring-cloud-starter-oauth2</artifactId> <!-- <artifactId>spring-cloud-starter-oauth2</artifactId>-->
</dependency> <!-- </dependency>-->
<dependency> <dependency>
<groupId>cn.zyjblogs.starter</groupId> <groupId>cn.zyjblogs.starter</groupId>
<artifactId>zyjblogs-common-spring-boot-starter</artifactId> <artifactId>zyjblogs-common-spring-boot-starter</artifactId>

View File

@ -1,11 +1,17 @@
package cn.zyjblogs.gateway.filter; package cn.zyjblogs.gateway.filter;
import cn.zyjblogs.common.entity.constant.HttpHeaderConstant; 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.ResponseObject;
import cn.zyjblogs.common.entity.response.ResponseResult; import cn.zyjblogs.common.entity.response.ResponseResult;
import cn.zyjblogs.common.entity.response.ResponseStatus; import cn.zyjblogs.common.entity.response.ResponseStatus;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.Jwts;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
@ -43,7 +49,7 @@ import java.util.List;
public class AuthFilter implements GlobalFilter { public class AuthFilter implements GlobalFilter {
private final WhiteListProperties whiteListProperties; private final WhiteListProperties whiteListProperties;
private AntPathMatcher antPathMatcher = new AntPathMatcher(); private AntPathMatcher antPathMatcher = new AntPathMatcher();
private String SIGNING_KEY="zyjblogs123";
@Override @Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
@ -98,6 +104,8 @@ public class AuthFilter implements GlobalFilter {
return false; return false;
} }
String jwt = token.replace(HttpHeaderConstant.AUTHORIZATION_TYPE + " ", ""); 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; return true;
} }

View File

@ -78,6 +78,12 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId> <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> </dependency>
<dependency>
<groupId>cn.zyjblogs.starter</groupId>
<artifactId>zyjblogs-common-spring-boot-starter</artifactId>
<version>${zyjblogs.version}</version>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>

View File

@ -44,6 +44,7 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
private final JwtAccessTokenConverter accessTokenConverter; private final JwtAccessTokenConverter accessTokenConverter;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final DataSource dataSource; private final DataSource dataSource;
private final JwtTokenEnhancer jwtTokenEnhancer;
/** /**
* 令牌端点的安全约束 * 令牌端点的安全约束
* *
@ -56,7 +57,7 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
security security
//允许匿名访问端点url:/oauth/token_key //允许匿名访问端点url:/oauth/token_key
.tokenKeyAccess("permitAll()") .tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()") .checkTokenAccess("isAuthenticated()")
//TODO 待处理令牌访问安全 //TODO 待处理令牌访问安全
//允许匿名访问端点url:/oauth/check_token //允许匿名访问端点url:/oauth/check_token
// .checkTokenAccess("isAuthenticated()") // .checkTokenAccess("isAuthenticated()")
@ -83,12 +84,14 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
*/ */
@Override @Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints. endpoints.
//密码模式 //密码模式
authenticationManager(authenticationManager) authenticationManager(authenticationManager)
//授权码模式 //授权码模式
.authorizationCodeServices(authorizationCodeServices(dataSource)) .authorizationCodeServices(authorizationCodeServices(dataSource))
.tokenServices(tokenServices()) .tokenServices(tokenServices())
.accessTokenConverter(accessTokenConverter)
//允许表单认证 //允许表单认证
.allowedTokenEndpointRequestMethods(HttpMethod.POST); .allowedTokenEndpointRequestMethods(HttpMethod.POST);
} }
@ -107,8 +110,9 @@ public class AuthorizationServerConfiguration extends AuthorizationServerConfigu
tokenServices.setSupportRefreshToken(true); tokenServices.setSupportRefreshToken(true);
//令牌储存策略 //令牌储存策略
tokenServices.setTokenStore(tokenStore); tokenServices.setTokenStore(tokenStore);
tokenServices.setTokenEnhancer(accessTokenConverter); TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
enhancerChain.setTokenEnhancers(List.of(jwtTokenEnhancer,accessTokenConverter));
tokenServices.setTokenEnhancer(enhancerChain);
//令牌默认有效期 //令牌默认有效期
tokenServices.setAccessTokenValiditySeconds(7200); tokenServices.setAccessTokenValiditySeconds(7200);
//刷新令牌默认有效期3天 //刷新令牌默认有效期3天

View File

@ -11,7 +11,7 @@ import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
* @author zhuyijun * @author zhuyijun
*/ */
@Configuration @Configuration
public class TokenConfig { public class JwtTokenConfig {
private String SIGNING_KEY="zyjblogs123"; private String SIGNING_KEY="zyjblogs123";
/** /**
* 令牌存储策略 * 令牌存储策略

View File

@ -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<String, Object> 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;
}
}

View File

@ -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);
// }
//}

View File

@ -1,8 +1,11 @@
package cn.zyjblogs.oauth.config.security; 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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager; 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.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
@ -19,8 +22,11 @@ import javax.sql.DataSource;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { 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(); return super.authenticationManagerBean();
} }
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.authenticationProvider(oauthAuthenticationProvider)
// .userDetailsService(oauthUserDetailsService)
// .passwordEncoder(passwordEncoder());
// }
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); http.csrf().disable();

View File

@ -11,6 +11,7 @@ import lombok.Setter;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import java.util.Set; import java.util.Set;
@ -21,7 +22,7 @@ import java.util.Set;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Builder @Builder
public class OauthUserDetails implements UserDetails { public class OauthUserDetails implements UserDetails, Serializable {
private String id; private String id;
private String username; private String username;
@ -44,6 +45,91 @@ public class OauthUserDetails implements UserDetails {
private boolean accountNonLocked = true; private boolean accountNonLocked = true;
private boolean credentialsNonExpired = true; private boolean credentialsNonExpired = true;
private boolean enabled = 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<GrantedAuthority> 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 @Override
public Collection<? extends GrantedAuthority> getAuthorities() { public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities; return authorities;

View File

@ -15,7 +15,10 @@ import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
@Service /**
* @author zhuyijun
*/
@Service("oauthUserDetailsService")
@RequiredArgsConstructor @RequiredArgsConstructor
public class OauthUserDetailsServiceImpl implements UserDetailsService { public class OauthUserDetailsServiceImpl implements UserDetailsService {
private final UserService userService; private final UserService userService;