security实现用户认证,做了一个切面通过注释来给方法加日志打印,现在想要在日志打印出每次调用方法的当前用户,在切面中直接使用
SecurityContextHolder.getContext().getAuthentication()
获取不到对象
在security认证成功的回调方法里我是能正常获得信息的,下面是代码:
AjaxAuthenticationSuccessHandler.java
@Component
public class AjaxAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
....//省略其他代码
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.setContentType("application/json;charset=utf-8");
SysUser userDetails = (SysUser)authentication.getPrincipal();
//这个userDetails是有想要的内容的
....//省略其他代码
}
}
WebSecurityConfig.java
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
SecurityService securityService;
@Autowired
UrlFilterInvocationSecurityMetadataSource urlFilterInvocationSecurityMetadataSource;
@Autowired
UrlAccessDecisionManager urlAccessDecisionManager;
@Autowired
AuthenticationAccessDeniedHandler authenticationAccessDeniedHandler;
@Autowired
AjaxAuthenticationSuccessHandler authenticationSuccessHandler; // 登录成功返回的 JSON 格式数据给前端(否则为 html)
@Autowired
AjaxAuthenticationFailureHandler authenticationFailureHandler; // 登录失败返回的 JSON 格式数据给前端(否则为 html)
@Autowired
AjaxAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
ValidateCodeFilter validateCodeFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(securityService).passwordEncoder(new MyPasswordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
//设置哪些路径不进行权限控制,添加**允许所有地址可访问
web.ignoring().antMatchers("/console","/index**","/resources/**","/druid/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(validateCodeFilter,UsernamePasswordAuthenticationFilter.class).
csrf().disable()
.httpBasic().authenticationEntryPoint(authenticationEntryPoint)
.and()
.formLogin()
.usernameParameter("username")
.passwordParameter("password")
.failureHandler(authenticationFailureHandler)
.successHandler(authenticationSuccessHandler)
.permitAll()
.and()
.logout()
.permitAll()
.and()
.exceptionHandling()
.accessDeniedHandler(authenticationAccessDeniedHandler)
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O o) {
o.setSecurityMetadataSource(urlFilterInvocationSecurityMetadataSource);
o.setAccessDecisionManager(urlAccessDecisionManager);
return o;
}
});
}
}
MyLogAspect.java
@Aspect
@Component
public class MyLogAspect {
private final Logger logger = LoggerFactory.getLogger(MyLogAspect.class);
//定义切点
@Pointcut("@annotation(xxx)")
public void logPointCut() {
}
/**
* 在方法调用之前调用通知
*
* @param joinPoint 切点
*/
@Before("logPointCut()")
public void doBefore(JoinPoint joinPoint) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
System.out.println(SecurityContextHolder.getContext().getAuthentication());
//输出为null
}
}
网上查资料好像是说在认证完之后会清空SecurityContextHolder?那我在其他的类里面要获取当前用户该怎么办呢?得自己写session存吗?感觉应该是哪里没搞对,有大佬指教一下吗?
找到问题了,是在security的过滤器中选择不进行权限控制的路径里把我测试用的访问路径也加进去了,所以导致拿不到用户。参考帖子:https://blog.csdn.net/u012702547/article/details/105237938
WebSecurityConfig文件中的
@Override
public void configure(WebSecurity web) throws Exception {
//设置哪些路径不进行权限控制,添加**允许所有地址可访问
web.ignoring().antMatchers("/console","/index**","/resources/**","/druid/**");
}
如果要拿到当前用户,接口地址就不能在这里面,可找死我了~