Shiro Java安全框架 (认证、授权)--更新中

权限管理

权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。

  • 用户认证
  • 用户授权

Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份;

Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;


认证

用户认证的流程

  • 判断该资源能否不认证就能访问
  • 如果该资源需要认证才能访问,那判断该访问者是否认证
  • 如果还没有认证,那么需要进行认证
  • 认证通过后才能访问资源

调用流程:

  • 首先通过 new IniSecurityManagerFactory 并指定一个 ini 配置文件来创建一个 SecurityManager 工厂;

  • 接着获取 SecurityManager 并绑定到 SecurityUtils,这是一个全局设置,设置一次即可;

  • 通过 SecurityUtils 得到 Subject,其会自动绑定到当前线程;如果在 web 环境在请求结束时需要解除绑定;然后获取身份验证的 Token,如用户名 / 密码;

  • 调用 subject.login 方法进行登录,其会自动委托给 SecurityManager.login 方法进行登录;

  • 如果身份验证失败请捕获 AuthenticationException 或其子类,常见的如:

    • DisabledAccountException(禁用的帐号)、
    • LockedAccountException(锁定的帐号)、
    • UnknownAccountException(错误的帐号)、
    • ExcessiveAttemptsException(登录失败次数过多)、
    • IncorrectCredentialsException (错误的凭证)、
    • ExpiredCredentialsException(过期的凭证)等
      具体请查看其继承关系;对于页面的错误消息展示,最好使用如 “用户名 / 密码错误” 而不是 “用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;
  • 最后可以调用 subject.logout 退出,其会自动委托给 SecurityManager.logout 方法退出。


SecurityUtils.getSubject()

SecurityUtils.getSubject()是每个请求创建一个Subject, 并保存到ThreadContext的resources(ThreadLocal<Map<Object, Object>>)变量中,也就是一个http请求一个subject,并绑定到当前线程。

controller接受请求后

URL拦截

授权

用户授权的流程

  • 到达了用户授权环节,需要用户认证之后
  • 用户访问资源,系统判断该用户是否有权限去操作该资源
  • 如果该用户有权限才能够访问,如果没有权限就不能访问了

获取角色和权限

一个角色role对应多个权限,一个用户user对应多个角色
我们通过getSysUserRoleList和getPermissions分别获取角色列表和用户权限。

然后通过
user.hasRole("")或者role.hasPermission("")
检查用户是否有对某个操作的权限

密码加密和匹配

  • Subject

主体,代表了当前 “用户”
这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等;即一个抽象概念;所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者;

  • SecurityManager

安全管理器
即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;

  • Realm

域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限)
就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。


1.ShiroConfig配置类

添加@Configuration和@Bean

  • (1)创建ShiroFilterFactoryBean
    • 1.设置安全管理器SecurityManager
    • 2.创建Shiro内置过滤器,实现相关url拦截,使用LinkedHashMap添加
    • 3.设置调整页面
    • 4.设置过滤器
/**
         * anon:所有url都都可以匿名访问
         * authc: 需要认证才能进行访问
         * user: 如果使用 rememberme 可以直接访问
         * perms:该资源必须得到资源权限才可以访问
         * role:该资源必须得到角色权限才可以访问
         */
  • (2)创建DefaultWebSecurityManager(主要关联自定义realm)
  • (3)创建自定义Realm
  • (4 可选)配置ShiroDialect,配合thymeleaf使用

2.自定义Realm类

  • (1)可实现自定义的Credentials匹配类(实现自定义密码验证,通过添加到PostContruct作为类初始化执行)

  • (2)实现用户授权添加过程

        protected AuthorizationInfo doGetAuthorizationInfo
  • (3)实现用户认证过程

      protected AuthenticationInfo doGetAuthenticationInfo

自定义密码验证和加密(双MD5加盐salt 随机数)

Realm在验证用户身份的时候,要进行密码匹配。最简单的情况就是明文直接匹配,然后就是加密匹配,这里的匹配工作则就是交给CredentialsMatcher来完成的。

public interface CredentialsMatcher {
    boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info);
}

在涉及到密码存储问题上,应该加密 / 生成密码摘要存储,而不是存储明文密码。比如之前的 600w csdn 账号泄露对用户可能造成很大损失,因此应加密 / 生成不可逆的摘要方式存储。
这时就需要自定义一个CustomCredentialsMatcher 继承SimpleCredentialsMatcher 实现密码验证


RememberMe

  • cookie
  • rememberMeCookieManager

配置RememberMeManager

缓存

  • 使用缓存存储session(单服务器使用EhCacheManager)

  • 但是在分布式系统中,服务器集群情况下,EhCacheManager无法解决数据共享(会多次查询数据库),则选择使用redis作为缓存

Redis实现shiro缓存

  • 分布式共享session和授权信息需要把session和授权持久化到数据库或者缓存 shiro集群为了防止多次插查询数据库

  • 自定义实现类:或者使用crazycake开源shiro-redis实现好的工具

    • RedisSessionDAO 可以继承EnterpriseCacheSessionDAO实现session控制
    • RedisCache 继承Cache类实现具体redis操作缓存(remove、get、set、keys
    • RedisCacheManager 实现接口CacheManager的getCache获得RedisCache交给securityManager管理

    使用了ConcurrentMap管理数据和缓存,更加高效

缓存session和授权信息

1.基于EhCache缓存(效率不高,无法解决分布式问题)

2.基于Redis缓存(CrazyCake shiro-redis开源插件,效率高,可实现集群共享)

RedisConfig加载配置类

sessionManager管理session

创建cookie集群共享sessionid

Shiro配置类

ShiroFilterFactoryBean

一个工厂Bean,将ShiroFilter实例对象注入到Spring容器中去,这样Shiro基于url的方式进行请求过滤处理,把安全管理器添加到该bean中。

SecurityManager 管理认证和授权

1.SessionManager (管理session)

(1)SessionDao (自定义或者crazycake)
(2)cookie (存放JESSIONID)
(3)redisManager (管理redis)

2.CacheManager 保存用户信息和授权信息

方式一:EhCache实现缓存管理器,编写自定义缓存方式配置文件shiro-ehcache.xml
方式二:redis 做缓存
3.RememberMeManager

添加SimpleCookie作为RememberMeCookie

4.MyShiroRealm(自定义认证授权实现Realm类)

  • doGetAuthorizationInfo 授权
  • doGetAuthenticationInfo 认证
  • credentialsMatcher 配置凭证匹配器,双md5加盐加密
  • 本文作者: dzou | 微信:17856530567
  • 本文链接: http://www.dzou.top/post/712f837.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!