随着技术的迭代和变更,登录模块的也有了很多的变化,今天就主要来说说这个问题。
javaweb
javaweb时代是学校教学的一部分,他是使用了servlet来进行编程,有的教学会使用一些框架,例如springmvc。里面的登录案例都是使用session来做的。第一次登录做检验,如果成功,就把登录信息放在session里。而且session有超时时间控制,可以在对长期不访问的会剔除数据。session可以说是完美支持登录。
session是按照浏览器来作为唯一标识的,每次浏览器访问都会带着jssesionid,以此作为找到具体session的标志。
分布式
在单机不满足的时候,分布式出场了,开始有负载均衡的事情了,由于多个jvm一起协作了,session还是保持在单个jvm的,这个就没法用了,于是有了redis这种分布式缓存,也有ttl来控制时间。与浏览器交互的也就变成了token。没办法使用jsessionid了。于是服务端需要生成token,每次访问都带着这个token。
前后台分离
大型的项目前后台分离完全可以使用分布式的做法,但是也有小型的项目,尤其是使用springboot的时候,大家经常会遇到一个问题,就是使用session生成的id特别慢,会出现如下的日志。
Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [140,108] milliseconds.
网上可以查到解决方案。这里不做讨论。这是一个session的问题,那是否可以不用session呢,例如分布式的那种方案,不过为此加一个redis组建是很麻烦的事情,不如自己写一个简单满足需求的情况。 主要满足2个需求,一个是可以根据key找到value,第二个是要时间的过期限制。
public class LocalCache implements Runnable {
private static ScheduledExecutorService swapExpiredPool
= new ScheduledThreadPoolExecutor(1);
{
swapExpiredPool.scheduleWithFixedDelay(new LocalCache(), 5, 5, TimeUnit.MINUTES);
}
public static final long TIME = 30 * 60 * 1000;
private static class DataInfo {
public String value;
public long currentTime;
public DataInfo(String value, long currentTime) {
this.value = value;
this.currentTime = currentTime;
}
}
public static ConcurrentHashMap<String, DataInfo> hashMap = new ConcurrentHashMap<>();
public static void put(String key, String value) {
hashMap.put(key, new DataInfo(value, System.currentTimeMillis()));
}
public static String get(String key) {
DataInfo dataInfo = hashMap.get(key);
dataInfo.currentTime = System.currentTimeMillis();
return dataInfo.value;
}
@Override
public void run() {
long currentTime = System.currentTimeMillis();
Set<Map.Entry<String, DataInfo>> entries = hashMap.entrySet();
Iterator<Map.Entry<String, DataInfo>> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry<String, DataInfo> next = iterator.next();
long time = next.getValue().currentTime;
if (currentTime - time > TIME) {
iterator.remove();
}
}
}
}
我们用ConcurrentHashMap来做数据的保存,并且启动定时任务,每5分钟进行一次过期清理。只要找一个唯一id生成器就好。做为我们的key。每次只要把依旧传递token即可。