欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 前端技术 > javascript >内容正文

javascript

springboot整合spring security——登录管理 -凯发k8官方网

发布时间:2025/1/21 javascript 19 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 springboot整合spring security——登录管理 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

文章目录

    • 一、自定义认证成功、失败处理
      • 1.1 customauthenticationsuccesshandle
      • 1.2 customauthenticationfailurehandler
      • 1.3 修改 websecurityconfig
      • 1.4 运行程序
    • 二、session 超时
    • 三、限制最大登录数
    • 四、踢出用户
    • 五、退出登录
    • 六、session 共享
      • 6.1 导入依赖
      • 6.3 运行程序

一、自定义认证成功、失败处理

有些时候我们想要在认证成功后做一些业务处理,例如添加积分;有些时候我们想要在认证失败后也做一些业务处理,例如记录日志。

在之前的文章中,关于认证成功、失败后的处理都是如下配置的:

http.authorizerequests()// 如果有允许匿名的url,填在下面 // .antmatchers().permitall().anyrequest().authenticated().and()// 设置登陆页.formlogin().loginpage("/login").failure.defaultsuccess.permitall()...;

即 failure 指定认证失败后url,defaultsuccess 指定认证成功后url。我们可以通过设置 successhandler() 和 failurehandler() 来实现自定义认证成功、失败处理。

ps:当我们设置了这两个后,需要去除 failure 和 defaultsuccess 的设置,否则无法生效。这两套配置同时只能存在一套

1.1 customauthenticationsuccesshandle

自定义 customauthenticationsuccesshandler 类来实现 authenticationsuccesshandler 接口,用来处理认证成功后逻辑:

@component public class customauthenticationsuccesshandler implements authenticationsuccesshandler {private logger logger = loggerfactory.getlogger(getclass());@overridepublic void onauthenticationsuccess(httpservletrequest request, httpservletresponse response, authentication authentication) throws ioexception, servletexception {logger.info("登录成功,{}", authentication);response.sendredirect("/");} }

onauthenticationsuccess() 方法的第三个参数 authentication 为认证后该用户的认证信息,这里打印日志后,重定向到了凯发k8官方网首页。

1.2 customauthenticationfailurehandler

自定义 customauthenticationfailurehandler 类来实现 authenticationfailurehandler 接口,用来处理认证失败后逻辑:

@component public class customauthenticationfailurehandler implements authenticationfailurehandler {private logger logger = loggerfactory.getlogger(getclass());@autowiredprivate objectmapper objectmapper;@overridepublic void onauthenticationfailure(httpservletrequest request, httpservletresponse response, authenticationexception e) throws ioexception, servletexception {logger.info("登录失败,{}");response.setstatus(httpstatus.internal_server_error.value());response.setcontenttype("application/json;charset=utf-8");response.getwriter().write(objectmapper.writevalueasstring(e.getmessage()));} }

onauthenticationfailure()方法的第三个参数 exception 为认证失败所产生的异常,这里也是简单的返回到前台。

1.3 修改 websecurityconfig

@autowiredprivate customauthenticationfailurehandler customauthenticationfailurehandler;@autowiredprivate customauthenticationsuccesshandler customauthenticationsuccesshandler; @overrideprotected void configure(httpsecurity http) throws exception {http.authorizerequests()// 如果有允许匿名的url,填在下面//.antmatchers().permitall().anyrequest().authenticated().and()// 设置登陆页.formlogin().loginpage("/login").successhandler(customauthenticationsuccesshandler).failurehandler(customauthenticationfailurehandler) // .failure // .defaultsuccess.permitall();http.csrf().disable();}

1.首先将 customauthenticationsuccesshandler 和 customauthenticationfailurehandler注入进来
2.配置 successhandler() 和 failurehandler()
3.注释 failure 和 defaultsuccess

1.4 运行程序

运行程序,当我们成功登陆后,发现日志信息被打印出来,页面被重定向到了凯发k8官方网首页:

当我们认证失败后,发现日志中“登陆失败”被打印出来,页面展示了认证失败的异常消息:

二、session 超时

当用户登录后,我们可以设置 session 的超时时间,当达到超时时间后,自动将用户退出登录。

session 超时的配置是 springboot 原生支持的,我们只需要在 application.properties 配置文件中配置:

# session 过期时间,单位:秒 server.servlet.session.timeout=60

tip:
从用户最后一次操作开始计算过期时间。
过期时间最小值为 60 秒,如果你设置的值小于 60 秒,也会被更改为 60 秒。

我们可以在 spring security 中配置处理逻辑,在 session 过期退出时调用。修改 websecurityconfig 的 configure() 方法,添加:

.sessionmanagement()// 以下二选一//.invalidsessionstrategy()//.invalidsession;

spring security 提供了两种处理配置,一个是 invalidsessionstrategy(),另外一个是 invalidsession。

这两个的区别就是一个是前者是在一个类中进行处理,后者是直接跳转到一个 url。简单起见,我就直接用 invalidsession了,跳转到 /login/invalid,我们需要把该 url 设置为免授权访问, 配置如下:

@overrideprotected void configure(httpsecurity http) throws exception {http.authorizerequests()// 如果有允许匿名的url,填在下面.antmatchers("/login/invalid").permitall().anyrequest().authenticated().and()// 设置登陆页.formlogin().loginpage("/login").successhandler(customauthenticationsuccesshandler).failurehandler(customauthenticationfailurehandler).permitall().and() // .failure // .defaultsuccess.sessionmanagement().invalidsession;http.csrf().disable();}

在 controller 中写一个接口进行处理:

@requestmapping("/login/invalid") @responsestatus(httpstatus.unauthorized) @responsebody public string invalid() {return "session 已过期,请重新登录"; }

运行程序,登陆成功后等待一分钟(或者重启服务器),刷新页面:

三、限制最大登录数

接下来实现限制最大登陆数,原理就是限制单个用户能够存在的最大 session 数。

在上一节的基础上,修改 configure() 为:

@overrideprotected void configure(httpsecurity http) throws exception {http.authorizerequests()// 如果有允许匿名的url,填在下面.antmatchers("/login/invalid").permitall().anyrequest().authenticated().and()// 设置登陆页.formlogin().loginpage("/login").successhandler(customauthenticationsuccesshandler).failurehandler(customauthenticationfailurehandler).permitall().and() // .failure // .defaultsuccess.sessionmanagement().invalidsession//指定最大登录数.maximumsessions(1)//当达到最大值时,是否保留已经登录的用户.maxsessionspreventslogin(false)//当达到最大值时,旧用户被踢出后的操作.expiredsessionstrategy(customexpiredsessionstrategy);http.csrf().disable();}

增加了下面三行代码,其中:

maximumsessions(int):指定最大登录数
maxsessionspreventslogin(boolean):是否保留已经登录的用户;为true,新用户无法登录;为 false,旧用户被踢出
expiredsessionstrategy(sessioninformationexpiredstrategy):旧用户被踢出后处理方法

maxsessionspreventslogin()可能不太好理解,这里我们先设为 false,效果和 qq 登录是一样的,登陆后之前登录的账户被踢出。

编写 customexpiredsessionstrategy 类,来处理旧用户登陆失败的逻辑:

@component public class customexpiredsessionstrategy implements sessioninformationexpiredstrategy {private objectmapper objectmapper = new objectmapper();@overridepublic void onexpiredsessiondetected(sessioninformationexpiredevent event) throws ioexception, servletexception {map map = new hashmap<>();map.put("code",0);map.put("msg","已经另一台机器登录,您被迫下线。" event.getsessioninformation().getlastrequest());string s = objectmapper.writevalueasstring(map);event.getresponse().setcontenttype("application/json;charset=utf-8");event.getresponse().getwriter().write(s);} }

在 onexpiredsessiondetected() 方法中,处理相关逻辑,我这里只是简单的返回一句话。

执行程序,打开两个浏览器,登录同一个账户。因为我设置了 maximumsessions(1),也就是单个用户只能存在一个 session,因此当你刷新先登录的那个浏览器时,被提示踢出了。

下面我们来测试下 maxsessionspreventslogin(true) 时的情况,我们发现第一个浏览器登录后,第二个浏览器无法登录:

四、踢出用户

下面来看下如何主动踢出一个用户。

首先需要在容器中注入名为 sessionregistry 的 bean,这里我就简单的写在 websecurityconfig 中:

@overrideprotected void configure(httpsecurity http) throws exception {http.authorizerequests()// 如果有允许匿名的url,填在下面.antmatchers("/login/invalid").permitall().anyrequest().authenticated().and()// 设置登陆页.formlogin().loginpage("/login").successhandler(customauthenticationsuccesshandler).failurehandler(customauthenticationfailurehandler).permitall().and() // .failure // .defaultsuccess.sessionmanagement().invalidsession//指定最大登录数.maximumsessions(1)//当达到最大值时,是否保留已经登录的用户.maxsessionspreventslogin(false)//当达到最大值时,旧用户被踢出后的操作.expiredsessionstrategy(customexpiredsessionstrategy).sessionregistry(sessionregistry());http.csrf().disable();} @bean public sessionregistry sessionregistry() {return new sessionregistryimpl(); }

编写一个接口用于测试踢出用户:

@getmapping("/click")@responsebodypublic string removeusersessionbyusername(@requestparam string username) {int count = 0;list
网站地图