在整合springsecurity时遇到好几个问题,自动配置登录,下线,注销用户的操作,数据基于mybatis,模版引擎用的thymeleaf+bootstrap。

一、认证时密码的加密(passwordEncoder)原理如下

  •  其中 MD5Util是自定义密码加密工具类,随便写(注意添加盐值),注意点:理解匹配密码这个过程
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(new PasswordEncoder() {
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
//匹配 =================将用户表单登录的密码和encodedPasswor(这个值是从MyUserDetailService那边封装过来的))对比=================
return encodedPassword.equals(encode(rawPassword));
}
@Override
public String encode(CharSequence rawPassword) {
return MD5Util.encode((String) rawPassword);
}
}); }
  • MyUserDetailService是一个实现了UserDetailsService(springsecurity本身的接口)的方法,在这里面实现认证的数据查询及其登录用户权限查询封装。
  • 注意点:理解权限的赋予,即当前用户在这里就已经将所有的角色封装到springsecurity本身的User中了,但是在这里并没有认证成功,单纯的进行封装而已
@Service
public class MyUserDetailService implements UserDetailsService { @Autowired
UserService userService;
@Autowired
private SessionRegistry sessionRegistry; @Override
public UserDetails loadUserByUsername(String username) { if (username==null || username.equals("")) {
throw new UsernameNotFoundException("用户名不存在");
} Sys_User user=userService.getUserByName(username); //获得所有登录用户的信息
List<Object> list =sessionRegistry.getAllPrincipals();
for (Object object : list) {
if (((User)object).getUsername().equals(user.getUsername())) {
throw new SessionAuthenticationException("当前用户已经在线,登录失败");
}
System.out.println("getAllPrincipals的遍历"+((User)object).getUsername());
} //得到当前登录用户的信息
List<SimpleGrantedAuthority> authorities = new ArrayList<>(); for (Role role : user.getRoles()) {
//将得到的角色封装 在后面页面认证成功后会用到
authorities.add(new SimpleGrantedAuthority(role.getRolename()));
System.out.println("拥有的角色:"+role.getRolename());
}
return new User(user.getUsername(), user.getPassword(), authorities);
} }

二、授权时session的管理的配置(configure(HttpSecurity http)中)

  • 这个可以说是核心了,首先开启自动配置的注销功能(重点在开启否则默认的是自带的注销页面),LogoutUrl:自定义的登出URL,登出成功后的页面也可以自定义,这里就都不写了,在controller层实现自己定义的
//开启自动配置的注销功能。
http.logout().permitAll();//logoutUrl("/logout").logoutSuccessUrl("/");//表示注销成功以后来到首页
http //session管理
.sessionManagement()
.maximumSessions(1).maxSessionsPreventsLogin(true)
.sessionRegistry(getSessionRegistry());
  • http.sessionManagement().invalidSessionUrl("/login") 使用未过期但完全无效的sessionid用户发送请求,也会被重定向至特定url
 http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true)
  • MaximumLogins必须是-1以允许无限制的登录,或者是一个正整数来指定最大值
  • .maximumSessions(1)设置一个用户允许登录的个数    maxSessionsPreventsLogin 启用超出报错。

    在实测后发现设定上限后 最大登录次数为设定数目 +1 比如设定数2 则最大访问数目为3 第四次开始报错
    由此 如果我们用这个配置去指定用户单登录是不行的

  • http.sessionManagement().sessionFixation().migrateSession()spring security防止篡改session

三、自定义注销,下线的实现(重点)

  • 第一种实现单纯的进行了下线,暂时将session置为无效,并未去掉(看源码部分)
if (invalidateHttpSession) {//部分源码
HttpSession session = request.getSession(false);
if (session != null) {
logger.debug("Invalidating session: " + session.getId());
session.invalidate();
}
}
 @RequestMapping("/logout")
public String logout(HttpServletRequest request,HttpServletResponse response){
/**
* 第一种方式 单纯的离线 并未注销用户 即sessionID还在
*
*/ //获得注销用户的信息
Authentication auth=SecurityContextHolder.getContext().getAuthentication();
if (auth != null){
//设置为离线状态
new SecurityContextLogoutHandler().logout(request, response, auth);
}
return "redirect:/login"; }
  • 第二种彻底将sessionid从sessionRegistry中移除,实现用户注销
@RequestMapping("/logout")
public String logout2() { /**
* 第二种 将获取到登录用户信息后将该用户sessionID置为无效 然后再从sessionRegistry中移除
* 这种方式可以彻底注销用户登录状态
*/ List<Object> pList=sessionRegistry.getAllPrincipals();
List<SessionInformation> sessionsInfo = null;
for (Object principle : pList) {
sessionsInfo=sessionRegistry.getAllSessions(principle, false);
}
System.out.println("sesssion个数"+sessionsInfo.size());
for (SessionInformation sessionInformation : sessionsInfo) {
//获取当前sessionid
System.out.println("SESSIONID:"+sessionInformation.getSessionId());
sessionInformation.expireNow();//将session置为无效然后在下一步移除
sessionRegistry.removeSessionInformation(sessionInformation.getSessionId());
}
return "redirect:/login";
}

springboot整合springsecurity遇到的问题的更多相关文章

  1. boke练习: springboot整合springSecurity出现的问题,传递csrf

    boke练习: springboot整合springSecurity出现的问题,传递csrf freemarker模板 在html页面中加入: <input name="_csrf&q ...

  2. SpringBoot整合SpringSecurity简单实现登入登出从零搭建

    技术栈 : SpringBoot + SpringSecurity + jpa + freemark ,完整项目地址 : https://github.com/EalenXie/spring-secu ...

  3. SpringBoot整合SpringSecurity示例实现前后分离权限注解

    SpringBoot 整合SpringSecurity示例实现前后分离权限注解+JWT登录认证 作者:Sans_ juejin.im/post/5da82f066fb9a04e2a73daec 一.说 ...

  4. 9、SpringBoot整合之SpringBoot整合SpringSecurity

    SpringBoot整合SpringSecurity 一.创建项目,选择依赖 选择Spring Web.Thymeleaf即可 二.在pom文件中导入相关依赖 <!-- 导入SpringSecu ...

  5. boke练习: springboot整合springSecurity出现的问题,post,delete,put无法使用

    springboot 与 SpringSecurity整合后,为了防御csrf攻击,只有GET|OPTIONS|HEAD|TRACE|CONNECTION可以通过. 其他方法请求时,需要有token ...

  6. SpringBoot整合SpringSecurity实现JWT认证

    目录 前言 目录 1.创建SpringBoot工程 2.导入SpringSecurity与JWT的相关依赖 3.定义SpringSecurity需要的基础处理类 4. 构建JWT token工具类 5 ...

  7. SpringBoot 整合 SpringSecurity 梳理

    文档 Spring Security Reference SpringBoot+SpringSecurity+jwt整合及初体验 JSON Web Token 入门教程 - 阮一峰 JWT 官网 Sp ...

  8. SpringBoot整合SpringSecurity简单案例

    在我们开发项目的过程中经常会用到一些权限管理框架,Java领域里边经常用的可能就是shiro了,与之对应的还有SpringSecurity,SpringSecurity可以说是非常强大,与Spring ...

  9. SpringBoot整合SpringSecurity,SESSION 并发管理,同账号只允许登录一次

    重写了UsernamePasswordAuthenticationFilter,里面继承AbstractAuthenticationProcessingFilter,这个类里面的session认证策略 ...

随机推荐

  1. web框架解析

    一.白手起家 要想模拟出web请求响应的流程,先想想平时我们是怎么上网浏览网页的?首先打开浏览器,然后在地址栏中输入我们想要访问的页面,紧接着按下回车键Enter,最后跳转至目标页面(当然我们也会出现 ...

  2. 《Java Web开发实战》——Java工程师必备干货教材

    一年一度毕业季,又到了简历.offer漫天飞,失望与希望并存的时节.在IT行业,高校毕业生求职时,面临的第一道门槛就是技能与经验的考验,但学校往往更注重学生的理论知识,忽略了对学生实践能力的培养,因而 ...

  3. Vue.js 2.x API 知识梳理(一) 全局配置

    Vue.js 2.x API 知识梳理(一) 全局配置 Vue.config是一个对象,包含Vue的全局配置.可以在启动应用之前修改指定属性. 这里不是指的@vue/cli的vue.config.js ...

  4. 手工给程序插入 ShellCode

    PE格式是 Windows下最常用的可执行文件格式,理解PE文件格式不仅可以了解操作系统的加载流程,还可以更好的理解操作系统对进程和内存相关的管理知识,而有些技术必须建立在了解PE文件格式的基础上,如 ...

  5. Python Unittest进行接口测试的简单示例

    今年肯定是要把Python学到一定程度的,否则感觉自己混不下去了,那就开始半挣扎的咸鱼生活吧. ---------------------------------------------------- ...

  6. 关键字:__thread & pthread_key_t

    在说__thread之前,先来看看pthread_ket_t吧. 参考:http://blog.csdn.net/lmh12506/article/details/8452700 上面的博文说的比较通 ...

  7. 使用Feign通过服务名调用服务,找不到服务

    fegineureka 报错环境: eureka注册中心在远程服务器上 本地服务注册到远程的eureka注册中心 本地服务通过Fegin组件+服务名调用服务 报错时,注册中心的情况: Applicat ...

  8. mac下卸载android studio

    Execute these commands from the terminal rm -Rf /Applications/Android\ Studio.app rm -Rf ~/Library/P ...

  9. python 将字符串中的unicode字符码转换成字符

    将字符串str =’\u98ce\u534e\u7684\u51b2\u950b'转换成汉字显示 可以直接print输出 print u'\u98ce\u534e\u7684\u51b2\u950b' ...

  10. Cron 定时任务表达式

    Cron Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格式: Seconds Minutes Hours DayofMonth M ...