当前位置:首页 > 技术 > 正文内容

Spring Security(6)

Lotus2022-11-28 14:17技术

您好,我是湘王,这是我的51CTO博客,欢迎您来,欢迎您再来~


Spring Security使用MySQL保存cookie记录虽然方便,但是目前更多的主流互联网应用都是用NoSQL来保存非业务数据的,Spring Security也应该可以实现这个功能。之前Spring Security官方并不支持使用NoSQL来保存cookie,但这个问题对于一个爱钻研的码农来说应该只是个小CASE——毕竟只要有代码,就没有搞不定的问题——受JdbcTokenRepositoryImpl的启发,查看其源码,可以发现JdbcDaoSupport只是用来提供数据源,无实际意义,而PersistentTokenRepository才是要实现的接口。

JdbcTokenRepositoryImpl的源码非常简单,看懂了就能照着写出Mongo的实现。题外话:阅读源码是个能够很快提高开发能力的捷径,如Spring框架、Spark源码等等。

下面就来开始咱们的NoSQL改造DIY。

首先安装并运行mongodb(我用的是mongodb-4.2.6),可以是虚拟机,也可以是Docker。

再修改项目的pom.xml文件,增加mongodb依赖:

Spring Security(6)_mongodb


通过模仿JdbcDaoSupport,来自定义自己的MongoDaoSupport:

/**
* MongoDaoSupport
*
* @author 湘王
*/
@Component
public class MongoDaoSupport<T> {
@Autowired
private MongoTemplate mongoTemplate;

// 插入数据
public boolean insert(PersistentRememberMeToken token) {
if (Objects.isNull(token)) {
return false;
}

Object object = mongoTemplate.save(token);
if (Objects.nonNull(object)) {
return true;
}

return false;
}
}


然后再在MongoDaoSupport中增加两个重要的方法,让它支持Mongodb:

    // 查询数据
public PersistentRememberMeToken getTokenBySeries(String series) {
// // 如果是通过字符串方式诸葛插入字段值,那么通过mongoTemplate.findOne()得到的就是一个LinkedHashMap
// LinkedHashMap<String, String> map = (LinkedHashMap<String, String>) mongoTemplate
// .findOne(query, Object.class, "collectionName");
// return new PersistentRememberMeToken(map.get("username"), map.get("series"),
// map.get("tokenValue"), DateUtils.format()map.get("date"));
Query query = new Query(Criteria.where("series").is(series));
// // 这里原路返回PersistentRememberMeToken对象,不会是LinkedHashMap
// Object object = mongoTemplate.findOne(query, PersistentRememberMeToken.class);
// return (PersistentRememberMeToken) obejct;
return mongoTemplate.findOne(query, PersistentRememberMeToken.class);
}

// 更新数据
public boolean updateToken(String series, String tokenValue, Date lastUsed) {
Query query = new Query(Criteria.where("series").is(series));
Update update = new Update();
update.set("tokenValue", tokenValue);
update.set("date", lastUsed);
// // 这里不能用DateUtils.parse(new Date()),否则getTokenBySeries()方法会抛出非法参数异常
// update.set("date", DateUtils.parse(new Date()));
Object object = mongoTemplate.updateMulti(query, update, PersistentRememberMeToken.class);
if (Objects.nonNull(object)) {
return true;
}
return false;
}


然后再定义MongoTokenRepositoryImpl:

/**
* 自定义实现token持久化到mongodb
*
* @author 湘王
*/
public class MongoTokenRepositoryImpl implements PersistentTokenRepository {
@Autowired
private MongoDaoSupport<PersistentRememberMeToken> mongoDaoSupport;

@Override
public void createNewToken(PersistentRememberMeToken token) {
mongoDaoSupport.insert(token);
}

@Override
public void updateToken(String series, String tokenValue, Date lastUsed) {
mongoDaoSupport.updateToken(series, tokenValue, lastUsed);
}

@Override
public PersistentRememberMeToken getTokenForSeries(String series) {
return mongoDaoSupport.getTokenBySeries(series);
}

@Override
public void removeUserTokens(String username) {
}
}


接着在WebSecurityConfiguration中用自定义的MongoTokenRepositoryImpl代替JdbcTokenRepositoryImpl:

// NoSQL方式实现记住我
@Bean
public PersistentTokenRepository persistentTokenRepository() {
// 自定义mongo方式实现
MongoTokenRepositoryImpl mongoTokenRepository = new MongoTokenRepositoryImpl();
return mongoTokenRepository;
}


或者就直接(需要通过@Service注解注入):

Spring Security(6)_mongodb_02


运行postman测试,可以看到通过MongoDB实现了对cookie信息的存储与修改。

如果mongodb中多出了_class字段,可以加上额外的配置:

/**
* 去除_class字段
*
* @author 湘王
*/
@Configuration
public class MongoConfiguration implements InitializingBean {
@Autowired
@Lazy
private MappingMongoConverter mappingMongoConverter;

@Override
public void afterPropertiesSet() {
mappingMongoConverter
.setTypeMapper(new DefaultMongoTypeMapper(null));
}
}


多次运行可发现访问记录值的规律:

1、同一用户会有多条访问记录

如果每次都明确执行login方法,那么每次都会产生不同的记录,否则只会更新同一条记录的tokenValue和date值;

若token有效且未执行login方法,那么将更新最后一次产生的记录的tokenValue和date值。

2、这说明token条数是与login方法执行次数一一对应的;

3、只要token不失效,仅更新同一条记录series的token值。


访问数据记录:

Spring Security(6)_Spring Security_03


不管是Mongodb还是别的NoSQL,比如Redis,原理都是一样的。





感谢您的大驾光临!咨询技术、产品、运营和管理相关问题,请关注后留言。欢迎骚扰,不胜荣幸~


原文链接

扫描二维码推送至手机访问。

版权声明:本文来源于网络,仅供学习,如侵权请联系站长删除。

本文链接:https://news.layui.org.cn/post/1049.html

分享给朋友:

“Spring Security(6)” 的相关文章

你看好云原生吗?

我理解的云原生是一种思想。目前为止,再稍具体一点就是一种构建和运行应用程序的方法 ,是一套技术体系和方法论。 目前来看,互联网技术领域没有那么粗放了,可以看成从”一堆砖头“变成了码的整齐的砖头,各种人物资源、空间利用率更高了。 云原生还在不断的发展,一年前我看中了云原生的发展方向并展开了一系列的学习,目前工作中也只是稍有涉及,并不是主要工作,我还是非常期望可以从事云原生工作的,下面罗列一下云原...

#打卡不停更#[图文并茂]Packstack部署train版openstack

Packstack部署openstack-train 介绍如何在centos7.9中使用packstack部署openstack-train。 首先需要安装一个最小化安装的centos7.9,按照你的网络环境配置好网络,然后重启。 这里我的环境是VMware虚拟机,ip是192.168.10.30. 首先我们需要关闭防火墙和NetworkManager systemctl disable --n...

激活数据价值,探究DataOps下的数据架构及其实践丨DTVision开发治理篇

据中国信通院发布,2012 年到 2021 年 10 年间,我国数字经济规模由 12 万亿元增长到 45.5 万亿元,在整个 GDP 中的比重由 21.6% 提升至 39.8%。顺应时代发展新趋势,“数据” 成为新的生产要素已是毋庸置疑的共识。 如果说数据中台的崛起代表着企业数字化转型从流程驱动走向数据驱动,从数字化走向智能化。那么 DataOps,则是实现数据中台的一个优秀的理念或方法论。 D...

devops学习笔记-jenkins实现基础CI/CD操作

在之前的devops工具链中完成了jenkins以及gitlab配置之后,可以实现基础的CI/CD操作。 操作流程 整体的操作的流程如下所示: 在开发环境配置好代码之后,将代码上传到gitlab,jenkins拉取gitlab的代码,由maven插件build,打包好后,构建 docker镜像,上传到目标服务器中运行,可以通过tag选择版本代码。 本地编写代码 使用idea编写一个基础的spr...

C语言下for循环的一点技巧总结

for循环是普遍应用与各种计算机语言的一种循环方式。 一般情况下, for循环规则:for(条件一;条件二;条件三) 条件一为满足条件,也就是条件一为1时,进入这个for循环。条件二为循环条件,也就是说当条件二不满足时继续循环。条件三为循环递增条件,里面罗列循环节递增的方式。for循环在实际运行的时候是:首先判断条件一是否为1,为1时进入循环内的下一步,为0跳过整个for循环。其次判断条件二是否为...

Go实现优雅关机与平滑重启

前言 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式。而执行Ctrl+C关闭服务端时,会强制结束进程导致正在访问的请求出现问题。 实现原理 Go 1.8版本之后, http.Server 内置的 Shutdown() 方法就支持优雅地关机,说明一下Shutdown工作的机制:当程序检测到中断信号时,我们调用http...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。