Shiro作为Apache的项目,是程序员需要掌握的好框架, 它聚焦于每个项目必须用到的权限管理,
Shiro包含了好几个核心的概念
Realm
Subject - Pricipal
SessionManager
SessionDAO
Authenting
Authecate
他能够作为验证,原理上还是基于Cookie, 他的header中带着JsessionId=*******************的一个cookie,
有了这个值,就能在服务器端进行验证,如果是放在一个地方存储起来,并且能使用这个sessionId从服务器端能获取到对应的实体,说明这个sessionId是有效的, 这样就验证了这个sessionId是登录的, 但是这里确实有个问题, 如果是用postman这样的模拟post的工具, header中放入这个jsessionid的值, 当然前提就是这个人是自己知道用户名密码,然后登录了,并且通过谷歌浏览器等查看到了里面的jsessionId这个值, 然后再使用postman或者java代码发送了模拟的hppt请求。
所以按照道理来说 , 能知道这个jsessionid的人, 是知道用户名密码的人
这边保存服务器端的session的方式有两种, 一种是 单机的内存, 另一种是第三方存储器
他们在配置上有不同,
内存管理器, 比如在ShiroConfig中
@Bean
public CacheManager cacheManager() {
MemoryConstrainedCacheManager cacheManager=new MemoryConstrainedCacheManager();//使用内存缓存
return cacheManager;
}
这里使用的 类是这个 MemoryConstrainedCacheManager , 它把session 保存在内存中。
而如果用了Redis这种第三方的存储机制,或者数据库也可以的
@Bean
public CacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
return redisCacheManager;
}
这个CacheManager 就变成了RedisCacheManager, CacheManager可以理解为存储session 管理session的方式
还有SessionDAO, 就是Session的交互方式,
单机的内存方式 MemorySessionDAO , 这是Shiro系统默认带着的类。
private ConcurrentMap<Serializable, Session> sessions;
public MemorySessionDAO() {
this.sessions = new ConcurrentHashMap<Serializable, Session>();
}
public class MemorySessionDAO extends AbstractSessionDAO {
}
这些不同的机制的类 都需要把继承这个AbstractSessionDAO , 这个内存的SessionDAO保存的方式是一个 ConcurrentHashMap
,键值对, key值。
key值是使用 JavaUuidSessionIdGenerator ,产生的key值是String, String是实现了 Serializable
public class JavaUuidSessionIdGenerator implements SessionIdGenerator {
public Serializable generateId(Session session) {
return UUID.randomUUID().toString();
}
}
这个DAO基本上就是 创建 更新 删除 获取活跃session这几个功能, 有外部的线程 会去扫有多少活跃的session,然后定时清除过期的。
RedisSessionDAO 这个类可以和 MemorySessionDAO进行比照,
@Bean
public SessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
return redisSessionDAO;
}
RedisSessionDAO 同样包含了那几个必要的方法
RedisManager 是在其中的成员变量,比如它有 jedisPool ,可以拿到跟redis的连接 ,这就是管理
之前单机的内存Manager 是 MemoryConstrainedCacheManager.java , 他有ThreadLocal变量来保存当前线程的变量,可以防止Subject,
而我们这边的RedisManager也有 这个 ThreadLocal对象
另外如果需要定义 自己的比较类, 当前端传入 用户名 密码 , UserNamePasswordToken ,
有两种方式,一种是使用框架的类, 另一种方式是使用自定义的matcher类