首页 > 技术文章 > Shiro 核心知识

ruhuanxingyun 2019-12-07 10:22 原文

1. 简单介绍

  Apache Shiro是一个轻量级且功能强大的开源安全框架,基于角色的权限验证RBAC(Role Base Access Control),可以进行身份验证(登录)、授权(访问权限)、会话管理和加密,含有单点登录SSO、记住我、注销和缓存功能,URL和注解都可以实现鉴权和授权,但鉴权一般通过URL控制,而授权一般通过注解控制

2. shiro架构

  A. Subject:当前与软件进行交互的实体,如用户;

  B. SecurityManage:安全管理器,用于协调其托管组件以确保他们能够顺利进行协同工作;

  C. Authentication:用户身份识别,通常被称为用户‘登录’;

  D. Authorization:确定用户在该应用程序中的访问控制权限;

  E. SessionManager:创建和管理用户的session生命周期会话管理;

  F. CacheManager:创建和管理Cache组件使用实例的生命周期;

  G. Cryptography:对数据源数据进行加密算法;

  H. Realms:充当Shiro与应用程序之间的安全桥梁,获取应用程序中的用户、角色和权限信息,进行份验证和授权,需自己实现。

3. FilterChain:基于短路机制,即最先匹配原则,所以一般将/**=anthc放在最后面

过滤器名 类名 备注
anon org.apache.shiro.web.filter.authc.AnonymousFilter 匿名拦截器,即不需要登录即可访问,一般用于静态资源过滤,如:/static/**=anon
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter 基于表单拦截器,所有已登录用户可访问,即没有登录会跳转到登录页面,如:/**=anthc
user org.apache.shiro.web.filter.authc.UserFilter 用户拦截器,即用户已经身份验证或记住我登录的,如:/**=user
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter Basic Http身份验证拦截器
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter 权限授权拦截器,验证用户是否拥有所属权限,属性和roles一样,如:user/**=perms["user:create"]
port org.apache.shiro.web.filter.authz.PortFilter 端口拦截器,主要属性port(80):可以通过的端口;示例/test= port[80],如果用户访问该页面是非80,将自动将请求端口改为80并重定向到该80端口,其他路径/参数等都一样
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter rest风格拦截器,自动根据请求方法构建权限字符串;示例/users=rest[user],会自动拼出user:read,user:create,user:update,user:delete权限字符串进行权限匹配(所有都得匹配,isPermittedAll)
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter 角色授权拦截器,验证用户是否拥有所属角色;示例/admin/**=roles[admin]
ssl org.apache.shiro.web.filter.authz.SslFilter SSL拦截器,只有请求协议是https才能通过;否则自动跳转会https端口443;其他和port拦截器一样;
logout org.apache.shiro.web.filter.authz.LogoutFilter 退出拦截器,主要属性:redirectUrl:退出成功后重定向的地址(/),示例/logout=logout

4. 认证和授权实现

  (1) 登录认证:在应用程序中自定义一个继承了AuthorizingRelam抽象类的Relam类,重写doGetAuthenticationInfo方法

    A. 检查提交的进行认证令牌信息(principals:唯一标识subject的用户名或邮箱等,credentials:证明身份的证据,一般就是密码)【UsernamepasswordToken是最常见的用户名/密码身份验证方法,可以自定义继承AuthenticationToken接口即可】;

    B. 根据令牌信息从数据源中获取令牌信息;

    C. 对用户信息进行匹配验证【SecurityUtils.getSubject().login(token)】;

    D. 验证通过将返回一个封装了用户信息的AuthenticationInfo实例,验证失败则抛出AuthenticationException(层次结构很丰富)异常信息。

  (2) 权限授权:在应用程序中自定义一个继承AuthorizingRelam抽象类的Relam类,重写doGetAuthorizationInfo方法,当访问到页面的时候,链接配置了相应的权限或者Shiro标签才会执行此方法,否则不执行

    A. 获取登录用户名;

    B. 根据用户名去数据源查询用户角色和权限;

    C. 添加用户角色和权限【SimpleAuthorizationInfo类addRole()和addStringPermission()】。

  (3) 登录:只是处理登录的异常信息,具体的验证交给了Shiro处理,获取异常信息【request.getAttribute("shiroLoginFailure")】。

  认证过程源码分析参考:https://cloud.tencent.com/developer/article/1409287 或 https://www.jianshu.com/p/6abc22ec3cb8

5. Shiro配置

  Shiro核心是通过Filter来实现,所以通过URL规则来进行过滤和权限校验。

6. Shiro权限注解

  A. @RequiresAuthentication:表示当前的Subject已经通过login进行了身份验证;

  B. @RequiresUser:表示当前的subject已经身份验证或者通过记住我登录的;

  C. @RequiresGuest:表示当前的subject没有身份验证或者通过记住我登录的,即游客身份;

  D. @RequiresRoles(value={“admin”, “user”}, logical= Logical.AND):表示当前subject需要admin和user角色;

  E. @RequiresPermissions (value={“user:a”, “user:b”}, logical= Logical.OR):表示当前subject需要user:a或user:b权限;

  注意点:

    A. Shiro的认证注解处理是有内定的处理顺序的,如果有多个注解的话,前面的通过了会继续检查后面的,若不通过则直接返回,处理顺序依次为(与实际声明顺序无关):@RequiresRoles —>@RequiresPermissions  —>@RequiresAuthentication—>@RequiresUser—>@RequiresGuest;

    B. 以上注解可用在controller或service层中,建议将注解用在controller中,因为service层使用了spring事物注解,那么shiro注解将失效;

    C. shiro权限注解要生效,必须配置springAOP,通过设置shiro的SecurityManager 进行权限验证,即以下两个bean。

   /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * @return defaultAdvisorAutoProxyCreator
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);

        return defaultAdvisorAutoProxyCreator;
    }

   
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);

        return authorizationAttributeSourceAdvisor;
    }

7. Shiro异常类型

  (1)  身份认证异常

    A. 未知账户/用户不存在:org.apache.shiro.authc.UnknownAccountException;

    B. 账号锁定:org.apache.shiro.authc.LockedAccountException ;

    C. 用户禁用:org.apache.shiro.authc.DisabledAccountException;

    D. 错误的凭据:org.apache.shiro.authc.IncorrectCredentialsException ;

    E. 过期的凭据:org.apache.shiro.authc.ExpiredCredentialsException ;

    F. 不支持的身份令牌:org.apache.shiro.authc.pam.UnsupportedTokenException ;

    G. 登录重试次数超限:org.apache.shiro.authc.ExcessiveAttemptsException;

    H. 不允许用户多次登录:org.apache.shiro.authc.ConcurrentAccessException;

  (2) 权限异常

    A. 没有访问权限:org.apache.shiro.authz.HostUnauthorizedException、org.apache.shiro.authz.UnauthorizedException;

  (3) 授权异常:org.apache.shiro.authz.UnauthenticatedException、org.apache.shiro.authz.AuthorizationException

  (4) shiro全局异常:org.apache.shiro.ShiroException

8. Shiro缓存机制

 

 

 

可参考:Apache Shiro 参考文档

https://www.jianshu.com/p/054c925cd45d

推荐阅读