Spring Security11、登录用户管理

在后台管理中,我们常常需要查看在线的用户,然后管理用户,比如踢出用户等操作。

在 spring security 同样也可以做到,我们只需要在 HttpSecurity 中配置sessionRegistry,然后就可以在容器中注入SessionRegistry,调用其方法来实现。

一、注入SessionRegistry

SecurityConfig.java

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        ...(省略其他配置)...
        // 配置Session注册器
        .sessionRegistry(sessionRegistry());
}
    
/***
 * 注入Session注册器
 * 可使用该类获取在线的全部用户
 */
@Bean
public SessionRegistry sessionRegistry() {
    return new SessionRegistryImpl();
}

二、使用SessionRegistry获取在线用户+踢出用户

package com.miaopasi.securitydemo.controller;

import cn.hutool.core.lang.Console;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.miaopasi.securitydemo.config.security.SysUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 测试工具类
 *
 * @author lixin
 */
@RestController
public class TestController {
    private final SessionRegistry sessionRegistry;


    @Autowired
    public TestController(SessionRegistry sessionRegistry) {
        this.sessionRegistry = sessionRegistry;
    }

    /*** 获取全部在线用户 **/
    @GetMapping("/loginUsers")
    public List<Object> loginUsers() {
        return sessionRegistry.getAllPrincipals();
    }

    /*** 踢出指定用户 **/
    @PostMapping("kickOut")
    public Integer kickOutUser(@RequestParam(name = "username") String username) {
        // 1.在全部的登录用户中或者到指定对象
        final List<Object> allPrincipals = sessionRegistry.getAllPrincipals();
        final List<Object> collect = allPrincipals.stream().filter((item) -> Objects.equals(username, ((SysUser) item).getUsername())).collect(Collectors.toList());
        // 2.获取指定对象全部的Session(多登录)
        List<SessionInformation> sessions = new ArrayList<>();
        collect.forEach((item) -> sessions.addAll(sessionRegistry.getAllSessions(item, false)));
        // 3.设置Session过期
        sessions.forEach((item)->{
            // 立即过期
            item.expireNow();
            // 移除Session
            sessionRegistry.removeSessionInformation(item.getSessionId());
        });
        // 4.返回清除的记录数
        return sessions.size();
    }
}

三、测试接口

  • 登录用户 user1、user2、user3,然后调用接口 /loginUsers
[
    {
        "id": 1,
        "gmtCreate": "2021-08-07T11:18:21.524+0000",
        "gmtModified": null,
        "isDelete": false,
        "operator": "管理员",
        "sort": 0,
        "version": null,
        "username": "user1",
        "password": null,
        "status": 0,
        "remarks": "测试用户1",
        "authorities": [
            {
                "authority": "guest"
            }
        ],
        "enabled": true,
        "accountNonExpired": true,
        "accountNonLocked": true,
        "credentialsNonExpired": true
    },
    {
        "id": 2,
        "gmtCreate": "2021-08-07T14:13:18.784+0000",
        "gmtModified": null,
        "isDelete": false,
        "operator": "管理员",
        "sort": 0,
        "version": null,
        "username": "user2",
        "password": null,
        "status": 0,
        "remarks": "测试用户2",
        "authorities": [
            {
                "authority": "guest"
            }
        ],
        "enabled": true,
        "accountNonExpired": true,
        "accountNonLocked": true,
        "credentialsNonExpired": true
    },
    {
        "id": 3,
        "gmtCreate": "2021-08-07T14:13:38.176+0000",
        "gmtModified": null,
        "isDelete": false,
        "operator": "管理员",
        "sort": 0,
        "version": null,
        "username": "user3",
        "password": null,
        "status": 0,
        "remarks": "测试用户3",
        "authorities": [
            {
                "authority": "guest"
            }
        ],
        "enabled": true,
        "accountNonExpired": true,
        "accountNonLocked": true,
        "credentialsNonExpired": true
    }
]
  • 我们现在调用接口/kickOut踢出登录用user2
POST http://127.0.0.1:8080/kickOut

HTTP/1.1 200 
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Type: application/json
Transfer-Encoding: chunked
Date: Sat, 07 Aug 2021 14:17:28 GMT
Keep-Alive: timeout=60
Connection: keep-alive

1

Response code: 200; Time: 24ms; Content length: 1 bytes
  • 然后我们在登录了user2的浏览器上刷新
{
    "msg": "你的账号已在其他地方登录",
    "code": 1000
}
posted @ 2021-08-07 22:29  喵喵扑  阅读(407)  评论(0编辑  收藏  举报