优化代码

This commit is contained in:
zhuyijun 2022-10-16 21:19:27 +08:00
parent 46a1b2094d
commit 295cedcaed
7 changed files with 91 additions and 25 deletions

View File

@ -0,0 +1,54 @@
package cn.zyjblogs.config.security;
import cn.zyjblogs.starter.common.entity.constant.CommonRedisKeyConstant;
import cn.zyjblogs.starter.common.entity.context.BaseContext;
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.DefaultCsrfToken;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@Component
@RequiredArgsConstructor
public class OauthCsrfTokenRepository implements CsrfTokenRepository {
static final String DEFAULT_CSRF_COOKIE_NAME = "XSRF-TOKEN";
static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf";
static final String DEFAULT_CSRF_HEADER_NAME = "X-XSRF-TOKEN";
private String parameterName = "_csrf";
private String headerName = "X-XSRF-TOKEN";
private final RedisTemplateHandler<String, String> redisTemplateHandler;
@Override
public CsrfToken generateToken(HttpServletRequest httpServletRequest) {
return new DefaultCsrfToken(this.headerName, this.parameterName, this.createNewToken());
}
@Override
public void saveToken(CsrfToken csrfToken, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
String tokenValue = csrfToken == null ? "" : csrfToken.getToken();
String key = CommonRedisKeyConstant.XSRF_TOKEN + BaseContext.getUsername();
redisTemplateHandler.set(key, tokenValue);
redisTemplateHandler.expire(key, 30, TimeUnit.DAYS);
httpServletResponse.setHeader(headerName, tokenValue);
}
@Override
public CsrfToken loadToken(HttpServletRequest httpServletRequest) {
String tokenValue = redisTemplateHandler.get(CommonRedisKeyConstant.XSRF_TOKEN + BaseContext.getUsername());
if (tokenValue == null) {
return null;
}
return new DefaultCsrfToken(this.headerName, this.parameterName, tokenValue);
}
private String createNewToken() {
return UUID.randomUUID().toString();
}
}

View File

@ -26,6 +26,7 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private String resourceId; private String resourceId;
private final TokenStore tokenStore; private final TokenStore tokenStore;
private final WhiteListProperties whiteListProperties; private final WhiteListProperties whiteListProperties;
// private final CsrfTokenRepository oauthCsrfTokenRepository;
@Override @Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception { public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
@ -47,9 +48,8 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
*/ */
@Override @Override
public void configure(HttpSecurity http) throws Exception { public void configure(HttpSecurity http) throws Exception {
http http.csrf().disable()
.csrf() // .disable()
.disable()
//限制资源服务器作用范围为 "/user/**", "/demo/**" //限制资源服务器作用范围为 "/user/**", "/demo/**"
.requestMatchers().antMatchers("/v*/**", "/demo/**", .requestMatchers().antMatchers("/v*/**", "/demo/**",
String.join(",", whiteListProperties.getAllowPaths())) String.join(",", whiteListProperties.getAllowPaths()))

View File

@ -20,6 +20,7 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final OauthUserDetailsServiceImpl userDetailsService; private final OauthUserDetailsServiceImpl userDetailsService;
private final OauthAuthenticationProvider oauthAuthenticationProvider; private final OauthAuthenticationProvider oauthAuthenticationProvider;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
// private final CsrfTokenRepository oauthCsrfTokenRepository;
/** /**
* 密码编码解码 * 密码编码解码
* *

View File

@ -8,6 +8,8 @@ import org.springframework.security.oauth2.common.util.RandomValueStringGenerato
import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import java.util.concurrent.TimeUnit;
/** /**
* @author zhuyijun * @author zhuyijun
*/ */
@ -32,7 +34,9 @@ public class OauthAuthorizationCodeServices implements AuthorizationCodeServices
@Override @Override
public String createAuthorizationCode(OAuth2Authentication oAuth2Authentication) { public String createAuthorizationCode(OAuth2Authentication oAuth2Authentication) {
String code = this.generator.generate(); String code = this.generator.generate();
redisTemplateHandler.hPut(CommonRedisKeyConstant.AUTHORIZATION_CODE, code, oAuth2Authentication); redisTemplateHandler.set(CommonRedisKeyConstant.AUTHORIZATION_CODE + ":" + code, oAuth2Authentication);
redisTemplateHandler.expire(CommonRedisKeyConstant.AUTHORIZATION_CODE + ":" + code, 1, TimeUnit.MINUTES);
// redisTemplateHandler.hPut(CommonRedisKeyConstant.AUTHORIZATION_CODE, code, oAuth2Authentication);
return code; return code;
} }
@ -44,8 +48,10 @@ public class OauthAuthorizationCodeServices implements AuthorizationCodeServices
@SneakyThrows @SneakyThrows
@Override @Override
public OAuth2Authentication consumeAuthorizationCode(String code) throws InvalidGrantException { public OAuth2Authentication consumeAuthorizationCode(String code) throws InvalidGrantException {
OAuth2Authentication oAuth2Authentication = redisTemplateHandler.<String, OAuth2Authentication>hGet(CommonRedisKeyConstant.AUTHORIZATION_CODE, code); // OAuth2Authentication oAuth2Authentication = redisTemplateHandler.<String, OAuth2Authentication>hGet(CommonRedisKeyConstant.AUTHORIZATION_CODE, code);
redisTemplateHandler.hDelete(CommonRedisKeyConstant.AUTHORIZATION_CODE, code); // redisTemplateHandler.hDelete(CommonRedisKeyConstant.AUTHORIZATION_CODE, code);
OAuth2Authentication oAuth2Authentication = redisTemplateHandler.get(CommonRedisKeyConstant.AUTHORIZATION_CODE + ":" + code);
redisTemplateHandler.delete(CommonRedisKeyConstant.AUTHORIZATION_CODE + ":" + code);
return oAuth2Authentication; return oAuth2Authentication;
} }

View File

@ -5,16 +5,10 @@ import cn.zyjblogs.server.client.po.OauthClientDetail;
import cn.zyjblogs.starter.common.utils.bean.BeanUtils; import cn.zyjblogs.starter.common.utils.bean.BeanUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.ClientAlreadyExistsException; import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.ClientRegistrationException;
import org.springframework.security.oauth2.provider.ClientRegistrationService;
import org.springframework.security.oauth2.provider.NoSuchClientException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -31,16 +25,16 @@ public class OauthClientDetailsServiceImpl implements ClientDetailsService, Clie
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
@Override @Override
public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException { public OauthClientDetail loadClientByClientId(String clientId) throws ClientRegistrationException {
LambdaQueryWrapper<OauthClientDetail> wrapper = Wrappers.lambdaQuery(); LambdaQueryWrapper<OauthClientDetail> wrapper = Wrappers.lambdaQuery();
wrapper.eq(OauthClientDetail::getClientId,clientId); wrapper.eq(OauthClientDetail::getClientId, clientId);
return oauthClientDetailsMapper.selectOne(wrapper); return oauthClientDetailsMapper.selectOne(wrapper);
} }
@Override @Override
public void addClientDetails(ClientDetails clientDetails) throws ClientAlreadyExistsException { public void addClientDetails(ClientDetails clientDetails) throws ClientAlreadyExistsException {
OauthClientDetail oauthClientDetail = new OauthClientDetail(clientDetails); OauthClientDetail oauthClientDetail = new OauthClientDetail(clientDetails);
if (oauthClientDetail.getClientSecret() != null){ if (oauthClientDetail.getClientSecret() != null) {
oauthClientDetail.setClientSecret(passwordEncoder.encode(oauthClientDetail.getClientSecret())); oauthClientDetail.setClientSecret(passwordEncoder.encode(oauthClientDetail.getClientSecret()));
} }
oauthClientDetailsMapper.insert(oauthClientDetail); oauthClientDetailsMapper.insert(oauthClientDetail);
@ -49,31 +43,31 @@ public class OauthClientDetailsServiceImpl implements ClientDetailsService, Clie
@Override @Override
public void updateClientDetails(ClientDetails clientDetails) throws NoSuchClientException { public void updateClientDetails(ClientDetails clientDetails) throws NoSuchClientException {
LambdaUpdateWrapper<OauthClientDetail> updateWrapper = Wrappers.lambdaUpdate(); LambdaUpdateWrapper<OauthClientDetail> updateWrapper = Wrappers.lambdaUpdate();
updateWrapper.eq(OauthClientDetail::getClientId,clientDetails.getClientId()); updateWrapper.eq(OauthClientDetail::getClientId, clientDetails.getClientId());
OauthClientDetail oauthClientDetail = new OauthClientDetail(clientDetails); OauthClientDetail oauthClientDetail = new OauthClientDetail(clientDetails);
oauthClientDetailsMapper.update(oauthClientDetail,updateWrapper); oauthClientDetailsMapper.update(oauthClientDetail, updateWrapper);
} }
@Override @Override
public void updateClientSecret(String clientId, String clientSecret) throws NoSuchClientException { public void updateClientSecret(String clientId, String clientSecret) throws NoSuchClientException {
LambdaUpdateWrapper<OauthClientDetail> updateWrapper = Wrappers.lambdaUpdate(); LambdaUpdateWrapper<OauthClientDetail> updateWrapper = Wrappers.lambdaUpdate();
updateWrapper.eq(OauthClientDetail::getClientId,clientId).set(OauthClientDetail::getClientSecret,passwordEncoder.encode(clientSecret)); updateWrapper.eq(OauthClientDetail::getClientId, clientId).set(OauthClientDetail::getClientSecret, passwordEncoder.encode(clientSecret));
oauthClientDetailsMapper.update(null,updateWrapper); oauthClientDetailsMapper.update(null, updateWrapper);
} }
@Override @Override
public void removeClientDetails(String clientId) throws NoSuchClientException { public void removeClientDetails(String clientId) throws NoSuchClientException {
LambdaUpdateWrapper<OauthClientDetail> updateWrapper = Wrappers.lambdaUpdate(); LambdaUpdateWrapper<OauthClientDetail> updateWrapper = Wrappers.lambdaUpdate();
updateWrapper.eq(OauthClientDetail::getClientId,clientId); updateWrapper.eq(OauthClientDetail::getClientId, clientId);
oauthClientDetailsMapper.delete(updateWrapper); oauthClientDetailsMapper.delete(updateWrapper);
} }
@Override @Override
public List<ClientDetails> listClientDetails() { public List<ClientDetails> listClientDetails() {
List<OauthClientDetail> oauthClientDetails = oauthClientDetailsMapper.selectList(Wrappers.emptyWrapper()); List<OauthClientDetail> oauthClientDetails = oauthClientDetailsMapper.selectList(Wrappers.emptyWrapper());
if (CollectionUtils.isEmpty(oauthClientDetails)){ if (CollectionUtils.isEmpty(oauthClientDetails)) {
return new ArrayList<>(); return new ArrayList<>();
} }
return BeanUtils.map(oauthClientDetails,ClientDetails.class); return BeanUtils.map(oauthClientDetails, ClientDetails.class);
} }
} }

View File

@ -13,6 +13,10 @@ public class CommonRedisKeyConstant {
*/ */
public static final String REDIS_KEY_PRIVATE_RSA = "rsa:key:private_key"; public static final String REDIS_KEY_PRIVATE_RSA = "rsa:key:private_key";
public static final String REDIS_KEY_PUBLIC_RSA = "rsa:key:public_key"; public static final String REDIS_KEY_PUBLIC_RSA = "rsa:key:public_key";
/**
* csrf防护key
*/
public static final String XSRF_TOKEN = "XSRF_TOKEN:";
private CommonRedisKeyConstant() { private CommonRedisKeyConstant() {
} }

View File

@ -1,6 +1,8 @@
package cn.zyjblogs.starter.oauth.token; package cn.zyjblogs.starter.oauth.token;
import cn.zyjblogs.starter.common.autoconfigure.rsa.RsaKeyProperties; import cn.zyjblogs.starter.common.autoconfigure.rsa.RsaKeyProperties;
import cn.zyjblogs.starter.common.entity.constant.CommonRedisKeyConstant;
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -10,6 +12,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.util.StringUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -24,6 +27,7 @@ public class TokenConfig {
private final RsaKeyProperties rsaKeyProperties; private final RsaKeyProperties rsaKeyProperties;
private final OauthAccessTokenConverter oauthAccessTokenConverter; private final OauthAccessTokenConverter oauthAccessTokenConverter;
private final RedisTemplateHandler<String, String> redisTemplateHandler;
@Bean @Bean
public PasswordEncoder passwordEncoder() { public PasswordEncoder passwordEncoder() {
@ -46,7 +50,10 @@ public class TokenConfig {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
try { try {
if (rsaKeyProperties.getEnable()) { if (rsaKeyProperties.getEnable()) {
String publicKey = IOUtils.toString(Paths.get(rsaKeyProperties.getPubKeyPath()).toUri(), StandardCharsets.UTF_8); String publicKey = redisTemplateHandler.get(CommonRedisKeyConstant.REDIS_KEY_PUBLIC_RSA);
if (!StringUtils.hasLength(publicKey)) {
publicKey = IOUtils.toString(Paths.get(rsaKeyProperties.getPubKeyPath()).toUri(), StandardCharsets.UTF_8);
}
// 公钥验签 // 公钥验签
converter.setVerifierKey(publicKey); converter.setVerifierKey(publicKey);
} }