Shiro(1)---认证

0.什么是权限管理

  权限管理是系统的安全范畴,要求必须是合法的用户才可以访问系统(用户认证),且必须具有该 资源的访问权限才可以访问该 资源(授权)。
认证:对用户合法身份的校验,要求必须是合法的用户才可以访问系统。
授权:访问控制,必须具有该 资源的访问权限才可以访问该资源。

这里写图片描述

权限模型

  标准权限数据模型包括 :用户、角色、权限(包括资源和权限)、用户角色关系、角色权限关系。
这里写图片描述

权限分配

  通过UI界面方便给用户分配权限,对上边权限模型进行增、删、改、查操作。

权限控制

  基于角色的权限控制:根据角色判断是否有操作权限,因为角色的变化 性较高,如果角色修改需要修改控制代码,系统可扩展性不强。
  基于资源的权限控制:根据资源权限判断是否有操作权限,因为资源较为固定,如果角色修改或角色中权限修改不需要修改控制代码,使用此方法系统可维护性很强。建议使用。

权限管理的解决方案:

 粗粒度权限管理,对资源类型的权限管理。资源类型比如:菜单、url连接、用户添加页面、用户信息、类方法、页面中按钮。。
粗粒度权限管理比如:超级管理员可以访问户添加页面、用户信息等全部页面。
部门管理员可以访问用户信息页面包括 页面中所有按钮。

 细粒度权限管理,对资源实例的权限管理。资源实例就资源类型的具体化,比如:用户id为001的修改连接,1110班的用户信息、行政部的员工。
细粒度权限管理就是数据级别的权限管理。
细粒度权限管理比如:部门经理只可以访问本部门的员工信息,用户只可以看到自己的菜单,大区经理只能查看本辖区的销售订单。。

粗粒度和细粒度例子:
  系统有一个用户列表查询页面,对用户列表查询分权限,如果粗颗粒管理,张三和李四都有用户列表查询的权限,张三和李四都可以访问用户列表查询。
  进一步进行细颗粒管理,张三(行政部)和李四(开发部)只可以查询自己本部门的用户信息。张三只能查看行政部 的用户信息,李四只能查看开发部门的用户信息。细粒度权限管理就是数据级别的权限管理。

基于url的权限管理(掌握):

  企业开发常用的方法,使用web应用中filter来实现,用户请求url,通过filter拦截,判断用户身份是否合法(用户认证),判断请求的地址是否是用户权限范围内的url(授权)。

1.什么是Shiro

  shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权。
  spring中有spring security (原名Acegi),是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单。
  shiro不依赖于spring,shiro不仅可以实现 web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,shiro属于轻量框架,越来越多企业项目开始使用shiro。
使用shiro实现系统 的权限管理,有效提高开发效率,从而降低开发成本。

2.Shiro架构

  1. subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。

  2. securityManager:安全管理器,主体进行认证和授权都 是通过securityManager进行。

  3. authenticator:认证器,主体进行认证最终通过authenticator进行的。

  4. authorizer:授权器,主体进行授权最终通过authorizer进行的。

  5. sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。

  6. SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。

  7. cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。

  8. realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。
    注意:在realm中存储认证和授权的逻辑。

  9. cryptography:密码管理,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。
    比如 md5散列算法。

3.jar包

  与其它java开源框架类似,将shiro的jar包加入项目就可以使用shiro提供的功能了。shiro-core是核心包必须选用,还提供了与web整合的shiro-web、与spring整合的shiro-spring、与任务调度quartz整合的shiro-quartz等,下边是shiro各jar包的maven坐标。

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-quartz</artifactId>
            <version>1.2.3</version>
        </dependency>

4.Shiro认证

认证流程:
这里写图片描述

5.入门程序

配置shiro.ini

#配置数据
[users]
zhang=123
lisi=123

测试代码:

public void testShrio(){
        //构建SecurityManager工厂,IniSecurityManagerFactory可以从ini文件中初始化SecurityManager环境
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //通过工厂创建SecurityManager
        SecurityManager securityManager = factory.getInstance();
        //将securityManager设置到运行环境中
        SecurityUtils.setSecurityManager(securityManager);
        //创建一个Subject实例
        Subject subject = SecurityUtils.getSubject();
        //创建一个token令牌,记录用户认证的身份和凭证即帐号和密码
        UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123456");
        try {
            //用户登录
            subject.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
        //获取用户登录状态
        System.out.println("是否认证成功"+subject.isAuthenticated());
        subject.logout();
        System.out.println("是否认证成功"+subject.isAuthenticated());
    }

执行流程:

1.通过ini配置文件创建securityManager

2.调用subject.login方法主体提交认证,提交的token

3. securityManager进行认证,securityManager最终由ModularRealmAuthenticator进行认证。

4.ModularRealmAuthenticator调用IniRealm(给realm传入token) 去ini配置文件中查询用户信息

5.IniRealm根据输入的token(UsernamePasswordToken)从 shiro.ini查询用户信息,根据账号查询用户信息(账号和密码)
  如果查询到用户信息,就给ModularRealmAuthenticator返回AuthenticationInfo(认证信息)。
  如果查询不到,就给ModularRealmAuthenticator返回null

6.ModularRealmAuthenticator接收IniRealm返回的Authentication认证信息
  如果返回的认证信息是null,ModularRealmAuthenticator抛出异常(org.apache.shiro.authc.UnknownAccountException)
  如果返回的认证信息不是null(说明inirealm找到了用户),对IniRealm返回用户密码 (在ini文件中存在)和 token中的密码 进行对比,如果不一致抛出异常(org.apache.shiro.authc.IncorrectCredentialsException)

小结:

ModularRealmAuthenticator作用进行认证,需要调用realm查询用户信息(在数据库中存在用户信息)
ModularRealmAuthenticator进行密码对比(认证过程)。

realm:需要根据token中的身份信息去查询数据库(入门程序使用ini配置文件),如果查到用户返回认证信息,如果查询不到返回null。

6. 自定义realm

1.自定义一个realm类继承AuthorizingRealm类

public class CustomRealm extends AuthorizingRealm {

    public String getName() {
        return "customRealm";
    }
    // 授权
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        return null;
    }
    // 认证
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        //从token中获取用户身份信息
        String username = (String) token.getPrincipal();
        //...模拟从数据库中查询用户帐号是否存在...
        //如果查询不到,返回null
        if (!"zhang".equals(username)) {
            return null;
        }
        //...模拟从数据库中查询对应的密码...
        String password = "111111";
        //进行验证,并返回验证信息
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                username, password, this.getName());
        return simpleAuthenticationInfo;
    }
}

这里写图片描述

2.创建shiro.ini文件

[main]
#自定义 realm
customRealm=com.ak.shiro.CustomRealm
#将realm设置到securityManager
securityManager.realms=$customRealm
在进行测试时,只需修改上述测试代码中载入的ini配置文件即可。

补充:自定义realm类支持散列算法(md5+salt)

对数据加salt后进行md5加密(了解)

    public void testMD5(){
        String str1 = new Md5Hash("123456").toString();
        System.out.println("123456不加salt:\n"+str1);
        //md5加密,加盐,1次散列
        String str2 = new Md5Hash("123456", "dsadhfa",1).toString();
        System.out.println("123456加salt:\n"+str2);
        //md5加密,加盐,2次散列 md5(md5())
        String str3 = new Md5Hash("123456", "fadsfdd", 2).toString();
        System.out.println("123456加salt:\n"+str3);
        String str4 = new SimpleHash("md5", "123456", "fadsfdd", 2).toString();
        System.out.println("123456加salt:\n"+str4);
    }
实际步骤:

1.修改自定义realm类中的认证方法
在认证时,会对原始密码明文进行加盐加密处理,再做比较认证

// 认证
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal();
        //从数据库中取出md5加密后的密码和salt
        String password = "79c02336a80742b2953e15b3269650e7";
        String salt = "fadsfdd";
        //根据ini文件中的配置进行认证,如散列算法,散列次数
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                username, password, ByteSource.Util.bytes(salt), this.getName());
        return simpleAuthenticationInfo;
    }

2.修改shiro.ini文件

[main]
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数
credentialsMatcher.hashIterations=2

#将凭证匹配器设置到realm
customRealm=com.ak.shiro.CustomRealmMD5
customRealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$customRealm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值