• SSM项目实战 之 Shiro


    Shiro

    概述

    什么是权限管理
    	权限管理实现对用户访问系统的控制
    	用户可以访问而且只能访问自己被授权的资源
    	只要有用户和密码的系统,权限管理几乎都会出现
    	举例
    		给张三赋予“人力资源经理”角色
    		“人力资源经理”具有“查询员工”、“添加员工”、“修改员工”和“删除员工”权限。
    		此时张三能够进入系统,则可以进行这些操作;
    权限管理
    	认证
    		对于需要访问控制的资源用户首先经过身份认证
    		是判断一个用户是否为合法用户的处理过程
    	授权
    		认证通过后,还需用户具有资源的访问权限,方可访问
    		控制能够访问哪些资源
    shiro概述
    	Apache Shiro是Java的一个安全框架
    	Shiro是一个强大的简单易用的Java安全框架,主要用来更便捷的认证、授权、加密、会话管理、与Web集成、缓存等
    	Shiro使用起来小而简单
    	spring中有spring security ,是一个权限框架,它和spring依赖过于紧密,没有shiro使用简单。 
    	shiro不依赖于spring,shiro不仅可以实现web应用的权限管理,还可以实现c/s系统,分布式系统权限管理,
    	shiro属于轻量框架,越来越多企业项目开始使用shiro. 
    

    shiro核心概念

    核心类

    Authentication
    	身份认证/登录,验证用户是不是拥有相应的身份;
    Authorization
    	授权,即权限验证,验证某个已认证的用户是否拥有某个权限;
    Session Manager
    	会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;
    Cryptography
    	加密,保护数据的安全性
    Web Support
    	Web支持,可以非常容易的集成到Web环境;
    Caching
    	缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
    Concurrency
    	shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    Testing
    	提供测试支持;
    Run As
    	允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
    Remember Me
    	记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。
    

    整体类图

    主要概念

    Subject 
    	当前的操作用户
    		可以是人
    		爬虫
    		当前跟软件交互的东西
    	在shiro当中我们可以统称"用户"
    	在代码的任何地方,你都能轻易的获得Shiro Subject。
    	一旦获得Subject,你就可以立即获得你希望用Shiro为当前用户做的90%的事情(登录、退出、访问会话、执行授权检查等)
    SecurityManager
    	SecurityManager负责管理所有用户的安全操作
    	引用了多个内部嵌套安全组件,是Shiro框架的核心
    	你可以把它看成DispatcherServlet前端控制器。
    	用于调度各种Shiro框架的服务
    Realms
    	Realms则是用户的信息认证器和用户的权限认证器
    	执行认证(登录)和授权(访问控制)时,Shiro会从应用配置的Realm中查找很多内容
    	Realm 可以理解为读取用户信息、角色及权限的 DAO
    	SecurityManager要验证用户身份与权限,那么它需要从Realm获取相应的信息进行比较以确定用户身份是否合法;
    	可以把Realm看成DataSource,即安全数据源。
    

    Shiro架构

    整体架构图

    subject:主体
    	主体可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。 
    securityManager:安全管理器
    	主体进行认证和授权都是通过securityManager进行。 
    authenticator: 认证器
    	主体进行认证最终通过authenticator进行的。 
    authorizer: 授权器
    	主体进行授权最终通过authenticator进行的。 
    sessionManager:会话管理
    	web应用中一般是用web容器对session进行管理,shiro也提供一套session管理的方式。 
    sessionDao:
    	通过sessionDao管理session数据, 
    cacheManager: 缓存管理器
    	主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和 ehcache整合对缓存数据进行管理。 
    realm: 领域
    	相当于数据源,通过realm存取认证、授权相关数据。 
    cryptography: 密码管理
    	提供了一套加密/解密的组件,方便开发。比如 提供常用的散列、加/解密等功能。
    

    认证

    什么是认证

    • 身份认证,就是判断一个用户是否为合法用户的处理过程
    • 通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确

    关键对象

    Subject:主体
    	用户
    Principal:身份信息
    	是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等
    credential:凭证信息
    	是只有主体自己知道的安全信息,如密码、证书等。
    

    使用ini完成认证

    1.在Maven中添加依赖jar包

    <dependency>  
    	<groupId>org.apache.shiro</groupId>  
    	<artifactId>shiro-core</artifactId>  
    	<version>1.4.0</version>  
    </dependency>  
    

    2.添加shiro.ini配置文件

    ​ 首先准备一些用户身份/凭据(shiro.ini):

    [users]  
    itlike=1234
    my=1234
    

    3.登录与退出

    ​ 1.构建securityManager工厂
    ​ 2.通过工厂创建securityManager
    ​ 3.将securityManager设置到运行环境中
    ​ 4.创建一个Subject实例
    ​ 5.创建token令牌
    ​ 6.用户登录
    ​ 7.用户退出
    ​ 代码

    /*1.构建securityManager工厂*/
    IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    /*2.通过工厂创建securityManager*/
    SecurityManager securityManager = factory.getInstance();
    /*3.将securityManager设置到运行环境中*/
    SecurityUtils.setSecurityManager(securityManager);
    /*4.创建一个Subject实例*/
    Subject subject = SecurityUtils.getSubject();
    /*5.创建token令牌  用户名和密码*/
    UsernamePasswordToken token = new UsernamePasswordToken("itlike", "1234");
    /*6.用户登陆*/
    try {
    	subject.login(token);
    } catch (UnknownAccountException e) {
    	System.out.println("用户名不存在");
    	e.printStackTrace();
    }catch (IncorrectCredentialsException e){
    	System.out.println("密码错误");
    	e.printStackTrace();
    }
    System.out.println("是否认证"+subject.isAuthenticated());
    /*7.用户退出*/
    subject.logout();
    System.out.println("是否认证"+subject.isAuthenticated());
    

    认证流程

    认证流程图

    认证代码执行流程

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

    ​ 2.securityManager通过Authenticator(认证器)进行认证;

    ​ 3.Authenticator的实现ModularRealmAuthenticator调用realm从ini配置文件取用户真实的账号和密码

    ​ 4.IniRealm先根据token中的账号去ini中找该账号,如果找不到则给ModularRealmAuthenticator返回null,如果找到则匹配密码,匹配密码成功则认证通过。

    ​ 5、最后调用Subject.logout进行退出操作。

    自定义realm

    1.创建一个类继承AuthorizingRealm

    2.覆盖doGetAuthenticationInfo方法,在此方法当中数据库获取用户,交有验证器去验证

    public class EmployeeRealm extends AuthorizingRealm {
    
        @Autowired
        private EmployeeService employeeService;
    
        /*认证*/
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("来到了认证-------");
            /*获取身份信息*/
            String username = (String)token.getPrincipal();
            System.out.println(username);
            /*根据用户名当中查询有没有当前用户*/
            Employee employee = employeeService.getEmployeeWithUserName(username);
            System.out.println(employee);
            if (employee == null){
                return null;
            }
            /*认证*/
            /*参数: 主体,正确的密码,盐,当前realm名称*/
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                    employee,
                    employee.getPassword(),
                    ByteSource.Util.bytes(employee.getUsername()),
                    this.getName());
    
            return info;
        }
    	
        /*授权
         web  doGetAuthorizationInfo 什么时候调用
         1.发现访问路径对应的方法上面 有授权注解  就会调用doGetAuthorizationInfo
         2.页面当中有授权标签  也会调用doGetAuthorizationInfo
        * */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            return null;
        }
    }	
    

    3.在ini文件当中进行配置

    myRealm=MyRealm
    securityManager.realms=$myRealm
    

    散列密码

    概述

    • 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法
    • 一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等

    使用shiro进行散列密码

    ​ Md5Hash
    ​ SimpleHash
    ​ 示例

    Md5Hash md5Hash = new Md5Hash("itlike");
    System.out.println(md5Hash);
    /*通过加盐的方式来对密码进一步保护*/
    Md5Hash md5Hash2 = new Md5Hash("itlike","myxq");
    System.out.println(md5Hash2);
    /*可进行二次散列*/
    Md5Hash md5Hash3 = new Md5Hash("itlike","myxq",2);
    System.out.println(md5Hash3);
    
    /*使用SimpleHash*/
    SimpleHash simpleHash = new SimpleHash(
    		"md5",
    		"itlike",
    		"myxq",
    		2);
    System.out.println(simpleHash);
    

    realm中配置散列

    • 在ini文件当中进行散列
    • 要保证数据库中的密码是经过散列之后的
    [main]
    #定义凭证匹配器
    credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
    #散列算法
    credentialsMatcher.hashAlgorithmName=md5
    #散列次数
    credentialsMatcher.hashIterations=3
    
    #指定realm
    myRealm=com.itlike.MyRealm
    #配置散列
    myRealm.credentialsMatcher=$credentialsMatcher
    #配置自定义散列
    securityManager.realms=$myRealm
    

    授权

    什么是授权

    • 授权,即访问控制,控制谁能访问哪些资源。
    • 主体进行身份认证后需要分配权限,方可访问系统的资源。
    • 对于某些资源没有权限是无法访问的。

    使用ini形式配置权限信息

    在ini文件中用户、角色、权限的配置规则
    	用户名=密码,角色1,角色2...
    	首先根据用户名找角色,再根据角色找权限,角色是权限集合。
    权限字符串的规则
    	“资源标识符:操作:资源实例标识符”
    	对哪个资源的哪个实例具有什么操作
    	:”是资源/操作/实例的分割符
    	权限字符串也可以使用*通配符
    

    ​ 示例

    [users]
    #用户itlike的密码是1234,此用户具有role1和role2两个角色
    itlike=1234,role1,role2
    myxq=1234,role2
    
    [roles]
    #角色role1对资源user拥有create、update权限
    role1=user:create,user:update
    #角色role2对资源user拥有create、delete权限
    role2=user:create,user:delete
    #角色role3对资源user拥有create权限
    role3=user:create
    

    自定义Realm形式权限

    /*获取身份信息*/
    Object principal = principals.getPrimaryPrincipal();
    /*根据用户名查询该用户的角色和权限*/
    List<String> roles = new ArrayList();
    roles.add("role1");
    roles.add("role2");
    List<String> permissions = new ArrayList();
    permissions.add("user:create");
    permissions.add("user:delete");
    /*把角色和权限与subject关联在一起,返回*/
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.addRoles(roles);
    info.addStringPermissions(permissions);
    
  • 相关阅读:
    JAVA闰年测试与解决非法输入
    Junit介绍与实现
    等价类划分方法的应用
    使用Visual Studio 2013进行UI自动化测试
    简谈软件测试
    【Software Project Management】Quizs
    White box testing
    peer review
    闰年问题
    热烈庆贺清明小长假的到来
  • 原文地址:https://www.cnblogs.com/mumuyinxin/p/11282854.html
Copyright © 2020-2023  润新知