springboot所有的配置是无xml的,用webinitlizer继承
AbstractAnnotationConfigDispatcherServletInitializer
配置拦截器等
在实现类中getServletFilters
就可以开启拦截了DelegatingFilterProxy securityFilterChain = new DelegatingFilterProxy("springSecurityFilterChain");return new Filter[] {characterEncodingFilter, securityFilterChain};
在实现类中
@Override protected Class<?>[] getRootConfigClasses() { return new Class<?>[]{RootConfig.class,SecurityConfig.class}; }就可以注册一个拦截相关的实现类实现auto认证与http认证啦!!!
===================================ruo======================================
以下为我遇到的错误信息
1.csrfException,场景,因为我是通过webservice调用的 属于无状态请求,所以需要在securityConfig里设置.and().csrf().disable()禁用即可
2.AccessDeniedException: Access is denied
这个是指我没有访问这个url地址的权限
3.
loadUserByUsername(String username)soa架构下万年获取不到username的问题,这个教科书和百度上并没有具体的告诉我
.formLogin() .loginPage("/login") .loginProcessingUrl("/loginProcessing")
4.InternalAuthenticationService
UserAccountEntity类实现spring的 org.springframework.security.core.userdetails.UserDetails实现equals与hashCode方法
@Override public boolean equals(Object rhs) { if (!(rhs instanceof User) || (rhs == null)) { return false; } User user = (User) rhs; return (this.getPassword().equals(user.getPassword()) && this.getUsername().equals(user.getUsername()) && (this.isAccountNonExpired() == user.isAccountNonExpired()) && (this.isAccountNonLocked() == user.isAccountNonLocked()) && (this.isCredentialsNonExpired() == user.isCredentialsNonExpired()) && (this.isEnabled() == user.isEnabled())); } @Override public int hashCode() { int code = 9792; for (GrantedAuthority authority : getAuthorities()) { code = code * (authority.hashCode() % 7); } if (this.getPassword() != null) { code = code * (this.getPassword().hashCode() % 7); } if (this.getUsername() != null) { code = code * (this.getUsername().hashCode() % 7); } if (this.isAccountNonExpired()) { code = code * -2; } if (this.isAccountNonLocked()) { code = code * -3; } if (this.isCredentialsNonExpired()) { code = code * -5; } if (this.isEnabled()) { code = code * -7; } return code; }
5.客户端请求这个,不要去请求login这个地址
org.springframework.security.authentication.BadCredentialsException: Bad credentials
DaoAuthenticationProvider
if(!this.passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)) {这是由于我密码配置错误导致的,让我们加到config auth这个方法
auth.userDetailsService(spitterUserService).passwordEncoder(new BCryptPasswordEncoder());改成
auth.userDetailsService(spitterUserService).passwordEncoder(new Md5PasswordEncoder());
即可
6.问:如果不让springboot重定向 并且返回json
答:这个问题问的好,这是人唯一没有参照网上资料自己根据意思研发出来的
在SecurityConfig 中
.and() .formLogin() .loginPage("/login") .loginProcessingUrl("/loginProcessing") .successHandler(new AuthSeuccessHandlerController())配置
public class AuthSeuccessHandlerController extends BaseController implements AuthenticationSuccessHandler
在 onAuthenticationSuccess 实现方法中 authentication 参数就有你的用户信息了 你不必要再去数据库查一遍了通过reponse就可以返回json了 你可以随便折腾
配置了successHandler他就不会再重写向到项目+/了
=======================================ruo=========================================
第二部分 资源认证
当我不是用AOP架构进行认证时 就没有第二部分了
当spring security认证通过后会通过SecurityContextHolder存储在上下文之中
那么我的AOP如何才能与Authentication 进行匹配呢?答案是不可能除非重写一大堆filter
我采用的是token进行传输
我重写了restTemplate工具类 多封装了token进去了
接下来是重点:
.authorizeRequests() .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { @Override public <O extends FilterSecurityInterceptor> O postProcess(O fsi) { fsi.setAccessDecisionManager(new AccessDecisionManagerImpl(userAccountRepository)); /*fsi.setAuthenticationManager(authenticationManagerBean());*/ return fsi; } }) // .expressionHandler(new AbstractAuthenticationProcessingFilter()) .antMatchers("/").permitAll() .antMatchers("/menu/root").access("ROLE_ADMIN")这是我的认证核心,重写了FilterSecurityInterceptor,我是没有办法,因为无论是GET 还是 POST还是其它请求都无法通过 UsernamePasswordAuthenticationFilter 如果未通过 那么security会新增一个认证 那就是AnonymousAuthenticationFilter那么 Authentication 就是匿名用户了,回归正题:我们用一个类实现 AccessDecisionManager 重写decide,方法中有如下参数
Authentication authentication, Object o, Collection<ConfigAttribute> configAttributes
authentication就是认证信息, 这个咱们不用管,基本就是匿名认证用户,因为这是aop架构,o就是咱们的请求url,configAttribute就是角色信息,请参照SecurityConfig里的配置,如果我要拦截哪个路径并且只允许哪个角色访问那么这个类就包含了这些角色信息。
而为什么需要token 我们是需要往数据库里面查一遍user并且与这个configAttributes进行认证匹配的,如果匹配成功就reutrn;不成功就抛出异常。