返回顶部
首页 > 资讯 > 精选 >如何使用springSecurity+jwt实现互踢功能
  • 584
分享到

如何使用springSecurity+jwt实现互踢功能

2023-06-21 20:06:50 584人浏览 薄情痞子
摘要

小编给大家分享一下如何使用springSecurity+Jwt实现互踢功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!jwt介绍:    &

小编给大家分享一下如何使用springSecurity+Jwt实现互踢功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

jwt介绍:

        JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准( RFC 7519 ),定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息。

jwt认证流程介绍:

用户使用账号和面发出post请求; 

服务器使用私钥创建一个jwt; 

服务器返回这个jwt给浏览器; 

浏览器将该jwt串在请求头中像服务器发送请求; 

服务器验证该jwt; 

返回响应的资源给浏览器。

如何使用springSecurity+jwt实现互踢功能

一.思路:

原来的实现用户登录态是:
1.后台登陆成功后生成一个令牌(uuid)----JwtAuthenticationSuccesshandler
2.后台把它包装成jwt数据,然后返回给前端—JwtAuthenticationSuccessHandler
3.后台把它加入redis缓存中,并设置失效时间----JwtAuthenticationSuccessHandler
4.前端调用接口时,带入jwt
5.后台写个拦截器或者过滤器,在前端调用接口的时候,从request的header中获取jwt,在缓存中搜索,如果存在则处于登录态,并重置失效时间(这样用户在有效时间内就处于登录态)—JwtSecurityContextRepository
6.解释下:springSecurity是个过滤器琏,是由一个一个的过滤器组成的

现在的互踢:
1.后台在登陆成功后,用用户id组成一个key,查询Redis缓存中的value
2.和新的jwt比较,如果不一样则把查到的jwt当做key从redis中删掉,就是上面第三步存储的
3.把用户id组成一个key,把上面jwt当做value传入缓存中
4.在上面的第5步,也重置下我们这里存储的值

*上面 指的是原来的实现用户登录态

package com.lc.gansu.security.component.jwt;import com.fasterxml.jackson.databind.ObjectMapper;import com.lc.gansu.framework.core.ConstantOfReturnCode;import com.lc.gansu.framework.core.RedisKey;import com.lc.gansu.framework.core.ReturnObject;import com.lc.gansu.security.component.SecurityConstants;import com.lc.gansu.security.domain.User;import com.lc.gansu.security.utility.JWTHS256;import lombok.extern.slf4j.Slf4j;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.security.core.Authentication;import org.springframework.security.WEB.WebAttributes;import org.springframework.security.web.authentication.AuthenticationSuccessHandler;import javax.servlet.Http.httpservletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.PrintWriter;import java.util.Objects;import java.util.UUID;import java.util.concurrent.TimeUnit;@Slf4jpublic class JwtAuthenticationSuccessHandler implements AuthenticationSuccessHandler {    //private final RequestCache requestCache = new HttpSessionRequestCache();    private final ObjectMapper jacksonObjectMapper;    private final RedisTemplate<String, Object> redisTemplate;    public JwtAuthenticationSuccessHandler(ObjectMapper jacksonObjectMapper, RedisTemplate<String, Object> redisTemplate) {        this.jacksonObjectMapper = jacksonObjectMapper;        this.redisTemplate = redisTemplate;    }    @Override    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {        log.info("JwtAuthenticationSuccessHandler=success");        clearAuthenticationAttributes(request);        handle(response, authentication);    }    protected final void clearAuthenticationAttributes(HttpServletRequest request) {        HttpSession session = request.getSession(false);        if (session == null) return;        session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);    }    protected void handle(HttpServletResponse response, Authentication authentication) throws IOException {        if (response.isCommitted()) {            log.debug("Response has already been committed.");            return;        }        User sysUser = (User) authentication.getPrincipal();        sysUser.setClazz(authentication.getClass());        //AuthenticationAdapter authenticationAdapter=AuthenticationAdapter.authentication2AuthenticationAdapter(authentication);        String authOfjson = jacksonObjectMapper.writeValueAsString(sysUser);        String subject = UUID.randomUUID().toString();        String authOfjwt = JWTHS256.buildJWT(subject, authOfjson);        response.addHeader("jwt", authOfjwt);        //跨域时允许header携带jwt        response.addHeader("Access-Control-Expose-Headers" ,"jwt");        redisTemplate.boundValueOps(SecurityConstants.getJwTKEy(subject)).set("w", 60, TimeUnit.MINUTES);        //---------互踢start-------------        // 在缓存中传入key="R_V_USERIDLOGINKEY_" + userId + "_LOGIN",value=SecurityConstants.getJwtKey(subject),有新登录时如果用户一样则把缓存里之前的jwt删除,这个:(redisTemplate.boundValueOps(SecurityConstants.getJwtKey(subject)).set("w", 60, TimeUnit.MINUTES);)        log.info("设置jwt,并在缓存中传入:{}",SecurityConstants.getJwtKey(subject));        String uuid = (String) redisTemplate.opsForValue().get(RedisKey.getUserIdKey(sysUser.getId()));        log.info("查询原有jwt:{}",uuid);        if(!SecurityConstants.getJwtKey(subject).equals(uuid)&& Objects.nonNull(uuid)){            assert uuid != null;            redisTemplate.delete(uuid);            log.info("删除原有jwt:{}",uuid);        }        redisTemplate.opsForValue().set(RedisKey.getUserIdKey(sysUser.getId()), SecurityConstants.getJwtKey(subject),60, TimeUnit.MINUTES);        log.info("在缓存里塞入新jwt:{}",SecurityConstants.getJwtKey(subject));        //---------互踢end----------------------        response.setContentType("application/json;charset=utf-8");        PrintWriter out = response.getWriter();        User returnSysUser = new User();        returnSysUser                .setName(sysUser.getName())                .setCurrentOrg(sysUser.getCurrentOrg())                .setOrgIdMapRoleList(sysUser.getOrgIdMapRoleList())                .setCurrentMenuList(sysUser.getCurrentMenuList())                .setOrgList(sysUser.getOrgList());        out.write(jacksonObjectMapper.writeValueAsString(new ReturnObject<>(this.getClass().getName(), ConstantOfReturnCode.GLOBAL_RESULT_SUCESS, "登录成功", returnSysUser)));        out.flush();        out.close();    }}
package com.lc.gansu.security.component.jwt;import com.fasterxml.jackson.core.type.TypeReference;import com.fasterxml.jackson.databind.ObjectMapper;import com.lc.gansu.framework.core.RedisKey;import com.lc.gansu.security.component.SecurityConstants;import com.lc.gansu.security.domain.User;import com.lc.gansu.security.utility.JWTHS256;import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.security.authentication.UsernamePassWordAuthenticationToken;import org.springframework.security.core.Authentication;import org.springframework.security.core.context.SecurityContext;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.web.context.HttpRequestResponseHolder;import org.springframework.security.web.context.SecurityContextRepository;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.Map;import java.util.Objects;import java.util.concurrent.TimeUnit;@Slf4jpublic class JwtSecurityContextRepository implements SecurityContextRepository {    protected final Log logger = LogFactory.getLog(this.getClass());    private final RedisTemplate<String, Object> redisTemplate;    private final ObjectMapper jacksonObjectMapper;    public JwtSecurityContextRepository(RedisTemplate<String, Object> redisTemplate, ObjectMapper jacksonObjectMapper) {        this.redisTemplate = redisTemplate;        this.jacksonObjectMapper = jacksonObjectMapper;    }    @Override    public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {        HttpServletRequest request = requestResponseHolder.getRequest();        return readSecurityContextFromJWT(request);    }    @Override    public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {    }    @Override    public boolean containsContext(HttpServletRequest request) {        return false;    }    private SecurityContext readSecurityContextFromJWT(HttpServletRequest request) {        SecurityContext context = generateNewContext();        String authenticationOfjwt = request.getHeader("jwt");        if (StringUtils.isNotBlank(authenticationOfjwt)) {            try {                Map<String, Object> map = JWTHS256.vaildToken(authenticationOfjwt);                if (Objects.nonNull(map) && map.size() == 2) {                    String subject = (String) map.get("subject");                    Boolean isExp = redisTemplate.hasKey(SecurityConstants.getJwtKey(subject));                    if (Objects.nonNull(isExp) && isExp) {//redis key 未过期                        redisTemplate.expire(SecurityConstants.getJwtKey(subject), 60, TimeUnit.MINUTES);//延期                        String obj = (String) map.get("claim");                        //AuthenticationAdapter authenticationAdapter=jacksonObjectMapper.readValue(obj, new TypeReference<>(){});                        //Authentication authentication=AuthenticationAdapter.authenticationAdapter2Authentication(authenticationAdapter);                        //Authentication authentication=jacksonObjectMapper.readValue(obj, new TypeReference<>(){});                        //Authentication authentication=jacksonObjectMapper.readValue(obj,Authentication.class);                        User sysUser = jacksonObjectMapper.readValue(obj, new TypeReference<User>() {                        });                        Authentication authentication = new UsernamePasswordAuthenticationToken(sysUser, null, sysUser.getAuthorities());                        context.setAuthentication(authentication);                        //-----互踢start-------                        if(Objects.nonNull(RedisKey.getUserIdKey(sysUser.getId()))) redisTemplate.expire(RedisKey.getUserIdKey(sysUser.getId()), 60, TimeUnit.MINUTES);                        //-----互踢end---------                        //if(obj instanceof Authentication){                        //context.setAuthentication((Authentication)obj);                        //}else log.error("jwt包含authentication的数据非法");                    } else log.error("jwt数据过期");                } else log.error("jwt数据非法");            } catch (Exception e) {                e.printStackTrace();                logger.error(e.getLocalizedMessage());            }        } else {            if (logger.isDebugEnabled()) {                logger.debug("No JWT was available from the HttpServletRequestHeader!");            }        }        return context;    }    protected SecurityContext generateNewContext() {        return SecurityContextHolder.createEmptyContext();    }}
package com.lc.gansu.framework.core;public class RedisKey {    //线上投放计划反馈结果催办    public static String getOlpmIdAndUserIdRedisKey(Long OlpmId, Long userId) {        return "R_V_OLPMURGE_" + OlpmId + "_" + userId;    }    //催办    public static String getOdpIdAndUserIdRedisKey(Long OdpId, Long userId) {        return "R_V_ODPMURGE_" + OdpId + "_" + userId;    }    //催办    public static String getJwtAndUrl(String jwt, String url) {        return "R_V_REPEAT_" + jwt + "_" + url;    }    //用户登录互踢    public static String getUserIdKey(Long userId) {        return "R_V_USERIDLOGINKEY_" + userId + "_LOGIN";    }}

---------------------------关键词:互踢

关键代码:

//---------互踢start-------------        // 在缓存中传入key="R_V_USERIDLOGINKEY_" + userId + "_LOGIN",value=SecurityConstants.getJwtKey(subject),有新登录时如果用户一样则把缓存里之前的jwt删除,这个:(redisTemplate.boundValueOps(SecurityConstants.getJwtKey(subject)).set("w", 60, TimeUnit.MINUTES);)        log.info("设置jwt,并在缓存中传入:{}",SecurityConstants.getJwtKey(subject));        String uuid = (String) redisTemplate.opsForValue().get(RedisKey.getUserIdKey(sysUser.getId()));        log.info("查询原有jwt:{}",uuid);        if(!SecurityConstants.getJwtKey(subject).equals(uuid)&& Objects.nonNull(uuid)){            assert uuid != null;            redisTemplate.delete(uuid);            log.info("删除原有jwt:{}",uuid);        }        redisTemplate.opsForValue().set(RedisKey.getUserIdKey(sysUser.getId()), SecurityConstants.getJwtKey(subject),60, TimeUnit.MINUTES);        log.info("在缓存里塞入新jwt:{}",SecurityConstants.getJwtKey(subject));        //---------互踢end----------------------
//-----互踢start-------                        if(Objects.nonNull(RedisKey.getUserIdKey(sysUser.getId()))) redisTemplate.expire(RedisKey.getUserIdKey(sysUser.getId()), 60, TimeUnit.MINUTES);                        //-----互踢end---------
//用户登录互踢    public static String getUserIdKey(Long userId) {        return "R_V_USERIDLOGINKEY_" + userId + "_LOGIN";    }

以上是“如何使用springSecurity+jwt实现互踢功能”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网精选频道!

--结束END--

本文标题: 如何使用springSecurity+jwt实现互踢功能

本文链接: https://lsjlt.com/news/300439.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何使用springSecurity+jwt实现互踢功能
    小编给大家分享一下如何使用springSecurity+jwt实现互踢功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!jwt介绍:    &...
    99+
    2023-06-21
  • 教你使用springSecurity+jwt实现互踢功能
    jwt介绍:         JWT是一种用于双方之间传递安全信息的简洁的、URL安全的表述性声明规范。JWT作为一个开放的标准( RFC 7519 ),定义了一种简洁的,自包含的方...
    99+
    2024-04-02
  • SpringSecurity整合springBoot、redis实现登录互踢功能
    背景 基于我的文章——《SpringSecurity整合springBoot、redis token动态url权限校验》。要实现的功能是要实现一个用户不可以同时在两台设备上登录,有两...
    99+
    2024-04-02
  • SpringSecurity整合springBoot、redis实现登录互踢功能的示例
    这篇文章主要介绍了SpringSecurity整合springBoot、redis实现登录互踢功能的示例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。背景要实现的功能是要实现...
    99+
    2023-06-15
  • Java SpringSecurity+JWT如何实现登录认证
    这篇文章主要介绍了Java SpringSecurity+JWT如何实现登录认证的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java SpringSecurity+JWT如何实现登录认证文...
    99+
    2023-07-02
  • SpringSecurity OAuth2如何实现单点登录和登出功能
    这篇文章将为大家详细讲解有关SpringSecurity OAuth2如何实现单点登录和登出功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1. 单点登录单点登录即有多个子系统,有一个认证中心...
    99+
    2023-06-29
  • 如何使用JWT实现单点登录
    本篇内容介绍了“如何使用JWT实现单点登录”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一、故事起源说起 ...
    99+
    2024-04-02
  • 如何使用Scala实现worldcount功能
    这篇文章主要讲解了“如何使用Scala实现worldcount功能”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用Scala实现worldcount功能”吧!新建ScalaWorldC...
    99+
    2023-06-02
  • 如何使用HTML实现截图功能
    这篇文章主要介绍了如何使用HTML实现截图功能,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。前言最近项目需求总是有HTML页面生成图片功能,...
    99+
    2024-04-02
  • 如何使用HTML5实现拍照功能
    这篇文章主要介绍“如何使用HTML5实现拍照功能”,在日常操作中,相信很多人在如何使用HTML5实现拍照功能问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用HTML5实...
    99+
    2024-04-02
  • 如何使用css实现计时功能
    这篇文章主要为大家展示了“如何使用css实现计时功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用css实现计时功能”这篇文章吧。<!DOCTYP...
    99+
    2024-04-02
  • 如何使用HTML5实现拖拽功能
    这篇文章给大家分享的是有关如何使用HTML5实现拖拽功能的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。   问题:突然奇想,想在电影网上加一个收藏(类似于购物车的东西),可以通...
    99+
    2024-04-02
  • 如何使用Redis实现秒杀功能
    这篇文章主要介绍如何使用Redis实现秒杀功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1. 怎样预防数据库超售现象设置数据库事务的隔离级别为Serializable(不可用)Serializable就是让数据库...
    99+
    2023-06-14
  • 如何使用nodejs实现路由功能
    这篇文章将为大家详细讲解有关如何使用nodejs实现路由功能,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。结构  项目结构如下  代码如下功能【router.js】// 加载所需模块var&nb...
    99+
    2023-06-14
  • 如何使用css实现分页功能
    本篇内容介绍了“如何使用css实现分页功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!首先创建一个html文件。在html文件中添加htm...
    99+
    2023-07-04
  • 如何使用vue实现打印功能
    这篇“如何使用vue实现打印功能”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“如何使用vue实现打印功能”文章吧。第一种方法...
    99+
    2023-07-04
  • 如何使用 PHP 实现搜索功能
    通过以下步骤实现 php 搜索功能:建立数据库连接定义搜索查询(使用 like 运算符)执行查询并获取结果显示搜索结果(按用户输入的搜索词筛选) 如何使用 PHP 实现搜索功能 搜索功...
    99+
    2024-05-02
    搜索 php mysql
  • 如何使用Vue-Router2实现路由功能
    这篇文章主要为大家展示了“如何使用Vue-Router2实现路由功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用Vue-...
    99+
    2024-04-02
  • 如何使用HTML5+CSS3实现拖放功能
    这篇文章主要为大家展示了“如何使用HTML5+CSS3实现拖放功能”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何使用HTML5+CSS3实现拖放功能”这篇文...
    99+
    2024-04-02
  • 如何使用SVG实现提示框功能
    小编给大家分享一下如何使用SVG实现提示框功能,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!NO.1前言Tooltips常被称为提示框(或信息提示框),提示框能够...
    99+
    2023-06-09
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作