本文参考至:https://blog.csdn.net/xusanhong/article/details/53260373
添加该功能是在原有功能上新增功能: SpringBoot +SpringSecurity+mysql 实现用户数据权限管理
spring-security 配置文件:添加用户并发登入的数量,session 失效跳转地址,实例化session 内存存储对象。
package com.zzg.security.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices;
import com.zzg.security.kaptch.filter.KaptchaFilter;
import com.zzg.security.provider.SpringSecurityProvider;
/**
* spring-security 配置文件
* @author zzg
*
*/
@Configuration
@EnableWebSecurity //开启Spring Security的功能
@EnableGlobalMethodSecurity(prePostEnabled=true)//开启注解控制权限
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* עSpringSecurityProvider
*/
@Autowired
private SpringSecurityProvider provider;
/**
*AuthenticationSuccessHandler
*/
@Autowired
private AuthenticationSuccessHandler securityAuthenticationSuccessHandler;
/**
* AuthenticationFailureHandler
*/
@Autowired
private AuthenticationFailureHandler securityAuthenticationFailHandler;
@Autowired
private DataSource dataSource;
/**
* 定义需要过滤的静态资源(等价于HttpSecurity的permitAll)
*/
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("static/css/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// TODO Auto-generated method stub
http.authorizeRequests()
.antMatchers("/login")
.permitAll() // 登入界面不需要权限
.antMatchers("/defaultKaptcha")
.permitAll() // 图像验证码不需要权限
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login") // 登入页面
.successHandler(securityAuthenticationSuccessHandler) //自定义成功处理器
.failureHandler(securityAuthenticationFailHandler) //自定义失败处理器
.permitAll()
.and()
.logout();
// 当通过JDBC方式记住密码时必须设置 key,key 可以为任意非空(null 或 "")字符串,但必须和 RememberMeService 构造参数的
// key 一致,否则会导致通过记住密码登录失败
http.authorizeRequests()
.and()
.rememberMe()
.rememberMeServices(rememberMeServices())
.key("INTERNAL_SECRET_KEY");
//在认证用户名之前认证验证码,如果验证码错误,将不执行用户名和密码的认证
http.addFilterBefore(new KaptchaFilter("/login", "/login?error"), UsernamePasswordAuthenticationFilter.class);
http.sessionManagement() //Session管理器
.maximumSessions(1) //相同用户并发数量
.sessionRegistry(getSessionRegistry()) //session内存操作对象
.expiredUrl("/login?error=session 失效"); //session 失效,跳转页面地址
}
@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
// 自定义身份验证提供者
builder.authenticationProvider(provider);
}
/**
* 返回 RememberMeServices 实例
*
* @return the remember me services
*/
@Bean
public RememberMeServices rememberMeServices() {
JdbcTokenRepositoryImpl rememberMeTokenRepository = new JdbcTokenRepositoryImpl();
// 此处需要设置数据源,否则无法从数据库查询验证信息
rememberMeTokenRepository.setDataSource(dataSource);
// 启动创建表,创建成功后注释掉
// rememberMeTokenRepository.setCreateTableOnStartup(true);
// 此处的 key 可以为任意非空值(null 或 ""),单必须和起前面
// rememberMeServices(RememberMeServices rememberMeServices).key(key)的值相同
PersistentTokenBasedRememberMeServices rememberMeServices =
new PersistentTokenBasedRememberMeServices("INTERNAL_SECRET_KEY", provider.getUserDetailsService(), rememberMeTokenRepository);
// 该参数不是必须的,默认值为 "remember-me", 但如果设置必须和页面复选框的 name 一致
rememberMeServices.setParameter("remember-me");
return rememberMeServices;
}
/**
* session 内存存储方式
* @return
*/
@Bean
public SessionRegistry getSessionRegistry(){
SessionRegistry sessionRegistry = new SessionRegistryImpl();
return sessionRegistry;
}
}
spring-security 发现登录同一个账号,并没有剔除前一个账号,这是如何实现的?
抛开框架暂且不说,如果是我直接写一个剔除前一个用户的话,我肯定是要得到全部用户,然后挨个挨个遍历筛选,如果存在当前登录用户就剔除前一个用户,这个需要使用if比较来实现的。
好了,问题找到了,因为SpringSecurity是通过管理UserDetails对象来实现用户管理的,按照上一步的原理,是需要进行比较实现效果的,然后呢,类的比较是不能用==比较的,类之间的比较是通过类的equals方法进行比较的,好了,问题找到了,我们自定义的User对象是没有实现equals方法的,好了,我们现在开始重写equals方法吧,关于重写的规则是:如果要重写equals方法,那么就必须要重写toStirng方法,如果要重写toString方法就最好要重写hashCode方法,所以我们需要在自定义的User对象中重写三个方法,hashCode、toString和equals方法。
@Override
public String toString() {
return this.nickname;
}
@Override
public int hashCode() {
return nickname.hashCode();
}
@Override
public boolean equals(Object obj) {
return this.toString().equals(obj.toString());
}
Okay,重启项目,剔除前一个用户成功!