Skip to content

Commit

Permalink
fix(*) Improved security for cleaning up on ThreadLocal.
Browse files Browse the repository at this point in the history
  • Loading branch information
yizzuide committed Apr 19, 2021
1 parent a11b8e2 commit 66544ad
Show file tree
Hide file tree
Showing 31 changed files with 177 additions and 96 deletions.
4 changes: 2 additions & 2 deletions Milkomeda/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<properties>
<java.version>1.8</java.version>
<project.release.version>3.12.8-SNAPSHOT</project.release.version>
<project.release.version>3.12.9-SNAPSHOT</project.release.version>
<spring-boot.version>2.2.4</spring-boot.version>
<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
<mybatis.starter.version>2.1.1</mybatis.starter.version>
Expand Down Expand Up @@ -67,7 +67,7 @@
<profile>
<id>sonatype-oss-release</id>
<properties>
<project.release.version>3.12.8</project.release.version>
<project.release.version>3.12.9</project.release.version>
</properties>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* @author yizzuide
* @since 2.0.0
* @version 3.5.0
* @see org.springframework.web.filter.CharacterEncodingFilter
* @see org.apache.coyote.Response#isCommitted()
* Create at 2019/12/12 17:48
*/
Expand All @@ -29,7 +30,7 @@ public void init(FilterConfig filterConfig) {

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 设置编码,防止Spring MVC注册Filter顺序问题导致乱码问题
// 设置编码,防止Spring MVC注册Filter顺序问题导致乱码问题(目前已经保证Spring Web MVC的CharacterEncodingFilter优先设置)
// servletRequest.setCharacterEncoding(Charset.defaultCharset().toString());
ServletRequest requestWrapper = servletRequest;
if (CometHolder.shouldWrapRequest()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
*
* @author yizzuide
* @since 1.14.0
* @version 2.0.5
* @version 3.12.9
* Create at 2019/11/11 15:48
*/
public class Crust {
Expand Down Expand Up @@ -178,11 +178,14 @@ public SecurityContext getContext() {
* 使登录信息失效
*/
public void invalidate() {
// Token方式下开启缓存时清空
if (getProps().isEnableCache() && getProps().isStateless()) {
CacheHelper.erase(lightCacheCrust, getUserInfo(Serializable.class).getUid(), id -> Crust.CATCH_KEY_PREFIX + id);
try {
// Token方式下开启缓存时清空
if (getProps().isEnableCache() && getProps().isStateless()) {
CacheHelper.erase(lightCacheCrust, getUserInfo(Serializable.class).getUid(), id -> Crust.CATCH_KEY_PREFIX + id);
}
} finally {
SecurityContextHolder.clearContext();
}
SecurityContextHolder.clearContext();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
*
* @author yizzuide
* @since 1.14.0
* @version 2.0.5
* @version 3.12.9
* Create at 2019/11/11 17:52
*/
@Slf4j
Expand Down Expand Up @@ -85,9 +85,12 @@ protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull Ht
unsuccessfulAuthentication(request, response, failed);
return;
}
chain.doFilter(request, response);
// 清空Token元数据(防止内存泄露)
crust.clearTokenMetaData();
try {
chain.doFilter(request, response);
} finally {
// 清空Token元数据(防止内存泄露)
crust.clearTokenMetaData();
}
}

protected void unsuccessfulAuthentication(HttpServletRequest request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
Expand Down Expand Up @@ -54,7 +55,9 @@ public class CrustConfigurerAdapter extends WebSecurityConfigurerAdapter {

@Override
public void configure(AuthenticationManagerBuilder auth) {
// 使用继承自DaoAuthenticationProvider
CrustAuthenticationProvider authenticationProvider = new CrustAuthenticationProvider(props, passwordEncoder);
// 扩展配置
configureProvider(authenticationProvider);
// 添加自定义身份验证组件
auth.authenticationProvider(authenticationProvider);
Expand All @@ -70,10 +73,12 @@ protected void configure(HttpSecurity http) throws Exception {
allowURLs.addAll(props.getAdditionPermitUrls());
}
// 标记匿名访问
// Find URL method map
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContextHolder.getApplicationContext().getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
Set<String> anonUrls = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
HandlerMethod handlerMethod = infoEntry.getValue();
// Has `CrustAnon` annotation on Method?
CrustAnon crustAnon = handlerMethod.getMethodAnnotation(CrustAnon.class);
if (null != crustAnon) {
anonUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
Expand Down Expand Up @@ -132,8 +137,10 @@ protected void configure(HttpSecurity http) throws Exception {
}

/**
* 配置Web资源,资源根路径需要配置静态资源映射:
* 配置Web资源,资源根路径需要配置静态资源映射<br>
* 如果配置了<code>spring.resources.add-mappings=false</code>,则需要添加下面的配置:
* <pre>
* &#64;Configuration
* public class WebMvcConfig implements WebMvcConfigurer {
* public void addResourceHandlers(ResourceHandlerRegistry registry) {
* // 设置静态资源,用于Spring Security配置
Expand Down Expand Up @@ -163,8 +170,11 @@ protected void additionalConfigure(ExpressionUrlAuthorizationConfigurer<HttpSecu
/**
* 自定义配置数据源提供及<code>PasswordEncoder</code>
* @param provider DaoAuthenticationProvider
* @see DaoAuthenticationProvider#setPasswordEncoder(PasswordEncoder)
*/
protected void configureProvider(DaoAuthenticationProvider provider) { }
protected void configureProvider(DaoAuthenticationProvider provider) {
provider.setUserDetailsService(userDetailsService());
}

/**
* 认证失败处理器
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public class CrustProperties {
private String tokenName = "token";

/**
* 是否使用Bcrypt,实现直接在密码里加salt(默认为true)
* 是否使用Bcrypt,实现直接在密码里加salt(默认为true)<br>
* 什么是Bcrypt?Bcrypt能够将salt添加到加密的密码中,解密时可以将salt提取出来
*/
private boolean useBcrypt = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
* @since 1.14.0
* Create at 2019/11/11 18:10
*/
public class PasswordEncoder {
public class PasswordEncoder implements org.springframework.security.crypto.password.PasswordEncoder {
private final static String MD5 = "MD5";
private final static String SHA = "SHA";

private Object salt;
private String algorithm;
private final Object salt;
private final String algorithm;

public PasswordEncoder(Object salt) {
this(salt, MD5);
Expand All @@ -29,42 +29,34 @@ public PasswordEncoder(Object salt, String algorithm) {
this.algorithm = algorithm;
}

/**
* 密码加密
* @param rawPass 源密码
* @return 加密结果
*/
public String encode(String rawPass) {
private String mergePasswordAndSalt(CharSequence password) {
if (password == null) {
password = "";
}
if ((salt == null) || "".equals(salt)) {
return password.toString();
} else {
return password + "{" + salt + "}";
}
}

@Override
public String encode(CharSequence rawPassword) {
String result = null;
try {
MessageDigest md = MessageDigest.getInstance(algorithm);
// 加密后的字符串
result = DataTypeConvertUtil.byte2HexStr(md.digest(mergePasswordAndSalt(rawPass).getBytes(StandardCharsets.UTF_8)));
result = DataTypeConvertUtil.byte2HexStr(md.digest(mergePasswordAndSalt(rawPassword).getBytes(StandardCharsets.UTF_8)));
} catch (Exception ignored) {
}
return result;
}

/**
* 密码匹配验证
* @param rawPass 明文
* @param encPass 密文
* @return 是否匹配
*/
public boolean matches(String rawPass, String encPass) {
String pass1 = "" + encPass;
String pass2 = encode(rawPass);
return pass1.equals(pass2);
}

private String mergePasswordAndSalt(String password) {
if (password == null) {
password = "";
}
if ((salt == null) || "".equals(salt)) {
return password;
} else {
return password + "{" + salt.toString() + "}";
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (encodedPassword == null || encodedPassword.length() == 0) {
return false;
}
return encodedPassword.equals(encode(rawPassword));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.yizzuide.milkomeda.hydrogen.i18n;

import org.springframework.lang.NonNull;
import org.springframework.web.servlet.i18n.AbstractLocaleResolver;

import javax.servlet.http.HttpServletRequest;
Expand Down Expand Up @@ -54,8 +55,9 @@ public Locale resolveLocale(HttpServletRequest request) {
return locale;
}*/

@NonNull
@Override
public Locale resolveLocale(HttpServletRequest request) {
public Locale resolveLocale(@NonNull HttpServletRequest request) {
// 是否有固定的设置
Locale defaultLocale = getDefaultLocale();
if (defaultLocale != null) {
Expand All @@ -67,7 +69,7 @@ public Locale resolveLocale(HttpServletRequest request) {
}

@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
public void setLocale(@NonNull HttpServletRequest request, HttpServletResponse response, Locale locale) {
setDefaultLocale(locale);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@AllArgsConstructor
public class I18nMessages {

private MessageSource messageSource;
private final MessageSource messageSource;

/**
* 获取国际化值
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,13 @@
String name() default "";

/**
* 唯一标识键,用于组成redis的key,支持Spring EL表达式,如:#id、#request.getHeader('token')、#env['title']、@env.get('spring.application.name')
* 唯一标识键,用于组成redis的key,支持Spring EL表达式,如:
* <ul>
* <li> 参数采集: #id </li>
* <li> 请求域: #request.getHeader('token') </li>
* <li> 自定义配置: #env['title'] </li>
* <li> Spring配置: @env.get('spring.application.name') </li>
* </ul>
* @return String
*/
String key() default "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@
* DelegatingBeanDefinitionRegistrar
* 动态注册数据选择策略切面
*
* <br><br>
* ImportBeanDefinitionRegistrar是Bean定义阶段注册器,适用于动态注册一个AspectJExpressionPointcutAdvisor <br>
* BeanPostProcessor是Bean的创建后置处理器,然后给它包装一个代理,但这里不适用
*
* @author yizzuide
* @since 3.4.0
* @see org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor
* @see org.springframework.aop.support.AbstractExpressionPointcut
* @see org.springframework.beans.factory.config.BeanPostProcessor
* Create at 2020/05/11 17:31
*/
public class DelegatingBeanDefinitionRegistrar implements EnvironmentAware, ImportBeanDefinitionRegistrar {
Expand All @@ -42,7 +49,7 @@ public void registerBeanDefinitions(@NonNull AnnotationMetadata importingClassMe
String beanName = "mk_sundial_advisor_" + strategy.getKeyName();
Advice advice = new DelegatingDataSourceAdvice(strategy.getKeyName());
BeanDefinition aspectJBean = BeanDefinitionBuilder.genericBeanDefinition(AspectJExpressionPointcutAdvisor.class)
.addPropertyValue("location", "$$aspectJAdvisor##")
.addPropertyValue("location", "$$aspectJAdvisor##") // Set the location for debugging.
.addPropertyValue("expression", strategy.getPointcutExpression())
.addPropertyValue("advice", advice)
.getBeanDefinition();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

/**
* DelegatingDataSourceAdvice
* 数据源切面代理
*
* @author yizzuide
* @since 3.4.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@Component
@ConfigurationProperties(prefix = SundialProperties.PREFIX)
public class SundialProperties {
// 配置前缀
// 当前配置前缀
static final String PREFIX = "milkomeda.sundial";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.filter.OrderedFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
Expand All @@ -29,7 +29,7 @@
*
* @author yizzuide
* @since 2.0.0
* @version 3.3.1
* @version 3.12.9
* Create at 2019/12/13 19:09
*/
@Configuration
Expand Down Expand Up @@ -70,7 +70,10 @@ public FilterRegistrationBean delegatingFilterRegistrationBean() {
delegatingFilterRegistrationBean.setFilter(new DelegatingFilterProxy("delegatingContextFilter"));
delegatingFilterRegistrationBean.setName("delegatingContextFilter");
delegatingFilterRegistrationBean.setUrlPatterns(Collections.singleton("/*"));
delegatingFilterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE + 40);
// Order defaults to after OrderedRequestContextFilter
// 解决无法从RequestContext获取信息的问题
int order = OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER - 104;
delegatingFilterRegistrationBean.setOrder(order);
return delegatingFilterRegistrationBean;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
public class CustomPropertySourceLocator implements /*PropertySourceLocator,*/ EnvironmentPostProcessor {

// 添加自定义属性来源方式一:实现PropertySourceLocator接口,把CollectionsPropertySourceLocator注册为Bean
// 添加自定义属性来源方式一:实现PropertySourceLocator接口,把CustomPropertySourceLocator注册为Bean
/*@Override
public PropertySource<?> locate(Environment environment) {
Map<String, Object> mapResource = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public void setConfigurableEnvironment(ConfigurableEnvironment configurableEnvir
}

/**
* 添加Spring环境变量
* 添加自定义数据源配置
* @param key 键
* @param value 值
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.springframework.lang.NonNull;

/**
* ParticleApplicationListener
* SourcesLogApplicationListener
*
* @author yizzuide
* @since 3.0.1
Expand Down
Loading

0 comments on commit 66544ad

Please sign in to comment.