springboot的cglib的代理问题
我在springboot项目中通过@configuration和@Bean注解添加了一个filter,可以正常工作;
之后想用AOP使该filter中每个方法被调用前都会输出log,但是在tomcat启动过程中这个filter(已经被cglib增强过了)的logger字段(该logger字段被声明为final,定义在org.springframework.web.filter.GenericFilterBean.java)为null抛出异常,不明白为什么,麻烦大家帮忙看看,谢谢。
调试中filter被cglib增强后的截图:
切面类:
package io.spring.infrastructure;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component
@Aspect
public class ShowLogger {
Logger logger = LoggerFactory.getLogger(getClass());
@Before("within(io.spring.api.security.*)")
public void outputLog(JoinPoint joinPoint) {
logger.info("@@@@@@@@@@@@@@@@: "+
joinPoint.getSignature());
}
}
Filter类:
package io.spring.api.security;
import io.spring.core.service.JwtService;
import io.spring.core.user.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.Optional;
//@SuppressWarnings("SpringJavaAutowiringInspection")
public class JwtTokenFilter extends OncePerRequestFilter {
@Autowired
private UserRepository userRepository;
@Autowired
private JwtService jwtService;
private String header = "Authorization";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
getTokenString(request.getHeader(header)).ifPresent(token -> {
jwtService.getSubFromToken(token).ifPresent(id -> {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
userRepository.findById(id).ifPresent(user -> {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
user,
null,
Collections.emptyList()
);
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
});
}
});
});
filterChain.doFilter(request, response);
}
private Optional<String> getTokenString(String header) {
if (header == null) {
return Optional.empty();
} else {
String[] split = header.split(" ");
if (split.length < 2) {
return Optional.empty();
} else {
return Optional.ofNullable(split[1]);
}
}
}
}
配置类:
package io.spring.api.security;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import static java.util.Arrays.asList;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${spring.h2.console.enabled:false}")
private boolean h2ConsoleEnabled;
@Bean
public JwtTokenFilter jwtTokenFilter() {
JwtTokenFilter T = new JwtTokenFilter();
return T;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
if (h2ConsoleEnabled)
http.authorizeRequests()
.antMatchers("/h2-console", "/h2-console/**").permitAll()
.and()
.headers().frameOptions().sameOrigin();
http.csrf().disable()
.cors()
.and()
.exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers(HttpMethod.GET, "/articles/feed").authenticated()
.antMatchers(HttpMethod.POST, "/users", "/users/login").permitAll()
.antMatchers(HttpMethod.GET, "/articles/**", "/profiles/**", "/tags").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(jwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(asList("*"));
configuration.setAllowedMethods(asList("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH"));
// setAllowCredentials(true) is important, otherwise:
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
configuration.setAllowCredentials(true);
// setAllowedHeaders is important! Without it, OPTIONS preflight request
// will fail with 403 Invalid CORS request
configuration.setAllowedHeaders(asList("Authorization", "Cache-Control", "Content-Type"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
stackoverflow传送门: https://stackoverflow.com/que...
简单来说, CGLib是生成一个委托类, 用来代理原类型的非final方法. 委托类中的属性为null是正常的. 你需要做的应该是把被代理类的方法上的final关键字去掉. 获取logger可以调用getLogger()方法.