Spring Security(6)
创始人
2024-02-23 04:38:30
0

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

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依赖:

 

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

/*** MongoDaoSupport** @author 湘王*/
@Component
public class MongoDaoSupport {@Autowiredprivate 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 map = (LinkedHashMap) 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 {@Autowiredprivate MongoDaoSupport mongoDaoSupport;@Overridepublic void createNewToken(PersistentRememberMeToken token) {mongoDaoSupport.insert(token);}@Overridepublic void updateToken(String series, String tokenValue, Date lastUsed) {mongoDaoSupport.updateToken(series, tokenValue, lastUsed);}@Overridepublic PersistentRememberMeToken getTokenForSeries(String series) {return mongoDaoSupport.getTokenBySeries(series);}@Overridepublic void removeUserTokens(String username) {}
}

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

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

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

 

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

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

/*** 去除_class字段** @author 湘王*/
@Configuration
public class MongoConfiguration implements InitializingBean {@Autowired@Lazyprivate MappingMongoConverter mappingMongoConverter;@Overridepublic void afterPropertiesSet() {mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null));}
}

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

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

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

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

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

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

访问数据记录:

 

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


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

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
苏州离哪个飞机场近(苏州离哪个... 本篇文章极速百科小编给大家谈谈苏州离哪个飞机场近,以及苏州离哪个飞机场近点对应的知识点,希望对各位有...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...