关于网上说的http方式配置无效问题,经验证,有点误导人,并且配置方式感觉过于复杂。
目前这种方式感觉是最简洁的一种方式。
一、核心配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private SessionRegistry sessionRegistry;
/**
* 设置URL的验证规则 Request层面的配置,对应XML Configuration中的<http>元素
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login.html", "/logout.html").permitAll()
.anyRequest().authenticated(); //登陆和登出可以匿名访问,其他的请求都必须要有权限认证
http.addFilterBefore(myValidCodeProcessingFilter(), UsernamePasswordAuthenticationFilter.class);//添加自定义验证规则
http.formLogin()
.loginPage("/login.html")//设置登陆页面
.loginProcessingUrl("/login")//登陆处理路径
http.logout()
.logoutUrl("/logout.html")//设置登出处理的url
.logoutSuccessUrl("/");//设置登出成功后跳转页面,默认是跳转到登录页面
http.headers()
.frameOptions()//解决不允许显示在iframe的问题
.sameOrigin()
.httpStrictTransportSecurity()
.disable();
http.csrf()
.disable();//关闭crsf
//session管理
//session失效后跳转
http.sessionManagement()
.invalidSessionUrl("/login.html");
http.sessionManagement()//只允许一个用户登录,如果同一个账户两次登录,那么第一个账户将被踢下线,跳转到登录页面
.maximumSessions(1)
.sessionRegistry(sessionRegistry)
.expiredUrl("/login.html");
}
//session失效跳转
private SessionInformationExpiredStrategy sessionInformationExpiredStrategy() {
return new SimpleRedirectSessionInformationExpiredStrategy("/login.html");
}
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
//SpringSecurity内置的session监听器
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
@Bean
public MyValidCodeProcessingFilter myValidCodeProcessingFilter() throws Exception {
MyValidCodeProcessingFilter filter = new MyValidCodeProcessingFilter();
filter.setAuthenticationManager(authenticationManagerBean());
//设置登陆成功后跳转的URL
filter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler("/index.html"));
//设置登陆失败后跳转的URL
//如果不设置这两个属性,会导致登陆成功后访问默认地址/
filter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/login.html?error=1"));
filter.setSessionAuthenticationStrategy(new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry));
return filter;
}
//其他代码省略···
}
二、重要的一步:重写User的hashCode、toString和equals方法。(如果继承的UserDetails,则重写UserDetails的三个方法)
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
/**
* @author Xie Yuan You
* <p>Created in 上午 11:30 2017/3/1 0001
* @version v.0.0.1
*
*/
public class SecurityUser extends User {
/**
*
*/
private static final long serialVersionUID = 1L;
private User sysUser;
public SecurityUser(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
public User getSysUser() {
return sysUser;
}
public void setSysUser(User sysUser) {
this.sysUser = sysUser;
}
/**
* 重写方法用于sessionRegistry
* @return
*/
@Override
public String toString() {
return super.getUsername();
}
/**
* 重写方法用于sessionRegistry
* @return
*/
@Override
public boolean equals(Object rhs) {
return this.toString().equals(rhs.toString());
}
/**
* 重写方法用于sessionRegistry
* @return
*/
@Override
public int hashCode() {
return super.getUsername().hashCode();
}
}
三、重写UsernamePasswordAuthenticationFilter:用户名密码验证通过后,注册session
public class MyValidCodeProcessingFilter extends UsernamePasswordAuthenticationFilter {
//省略部分代码......
@Resource
private SessionRegistry sessionRegistry;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
//省略部分代码......
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
//用户名密码验证通过后,注册session
sessionRegistry.registerNewSession(request.getSession().getId(),token.getPrincipal());
//省略部分代码......
this.setDetails(request, token);
return this.getAuthenticationManager().authenticate(token);
}
}