• Apache Shiro 权限框架


    分享一个视屏教程集合 http://www.tudou.com/home/konghao/item

    1.Shiro 

      Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序,可以和Spring无缝结合.关键步骤需要开发实现.

    2.主要功能 

    Authentication   认证

    Authorization   授权

    Cryptography   加密

    Session Management   Session 管理

    Web Integration   Web集成

    Integrations  和其他集成

      三个核心组件:Subject, SecurityManager 和 Realms[域].
      Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,可以把它认为是Shiro的“用户”概念。
      Subject:代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作,Current User。
      SecurityManager:它是Shiro框架的核心,管理所有的Subject
      Realm:Access your security data, Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
      从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。
      Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似ini的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm。【百度百科】
     
    3.POM.xml
    <!-- 添加Apache Shiro 依赖关系 -->
    <dependency>  
            <groupId>org.apache.shiro</groupId>  
            <artifactId>shiro-core</artifactId>  
            <version>1.2.2</version>  
     </dependency>  

    4.授权  

      也叫访问控制,在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、角色(Role)。

    5.主体【Subject】

      主体,即访问应用的用户,在Shiro中使用Subject代表该用户。用户只有授权后才允许访问相应的资源。

    6.资源【Resource】

      在应用中用户可以访问的任何东西,比如访问JSP页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。

    7.权限

      安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,如:

      访问用户列表页面

      查看/新增/修改/删除用户数据(即很多时候都是CRUD(增查改删)式权限控制)

      打印文档等等。。。

      如上可以看出,权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许,不反映谁去执行这个操作。所以后续还需要把权限赋予给用户,即定义哪个用户允许在某个资源上做什么操作(权限),Shiro不会去做这件事情,而是由实现人员提供。

    8.角色【Role】

      角色代表了操作集合,可以理解为权限的集合,一般情况下我们会赋予用户角色而不是权限,即这样用户可以拥有一组权限,赋予权限时比较方便。典型的如:项目经理、技术总监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限。

      隐式角色:

      显式角色:

        请baidu搜索“RBAC”和“RBAC新解”分别了解“基于角色的访问控制”“基于资源的访问控制(Resource-Based Access Control)”。

    9.Shiro 授权方式

      Shiro支持三种方式授权

      (1)编程式

    Subject subject = SecurityUtils.getSubject();
    if(subject.hasRole(“admin”)) {  
        //有权限  
    } else {  
        //无权限  
    }   

      (2)注解式:通过在执行的Java方法上放置相应的注解完成,没有权限将抛出相应的异常;

    @RequiresRoles("admin")  
    public void hello() {  
        //有权限  
    }   

      (3)JSP/GSP标签:在JSP/GSP页面通过相应的标签完成

    <shiro:hasRole name="admin">  
    <!— 有权限 —>  
    </shiro:hasRole>   

    授权

      (1)基于角色的访问控制(隐式角色)

        在ini配置文件配置用户拥有的角色(shiro-role.ini) 

    [users]  
    zhang=123,role1,role2  
    wang=123,role1 

      规则即:“用户名=密码,角色1,角色2”,如果需要在应用中判断用户是否有相应角色,就需要在相应的Realm中返回角色信息,也就是说Shiro不负责维护用户-角色信息,需要应用提供,Shiro只是提供相应的接口方便验证

      测试用例

    @Test  
    public void testHasRole() {  
        login("classpath:shiro-role.ini", "zhang", "123");  
        //判断拥有角色:role1  
        Assert.assertTrue(subject().hasRole("role1"));  
        //判断拥有角色:role1 and role2  
        Assert.assertTrue(subject().hasAllRoles(Arrays.asList("role1", "role2")));  
        //判断拥有角色:role1 and role2 and !role3  
        boolean[] result = subject().hasRoles(Arrays.asList("role1", "role2", "role3"));  
        Assert.assertEquals(true, result[0]);  
        Assert.assertEquals(true, result[1]);  
        Assert.assertEquals(false, result[2]);  
    }   

      Shiro提供了hasRole/hasRole用于判断用户是否拥有某个角色/某些权限;但是没有提供如hashAnyRole用于判断是否有某些权限中的某一个。  

    @Test(expected = UnauthorizedException.class)  
    public void testCheckRole() {  
        login("classpath:shiro-role.ini", "zhang", "123");  
        //断言拥有角色:role1  
        subject().checkRole("role1");  
        //断言拥有角色:role1 and role3 失败抛出异常  
        subject().checkRoles("role1", "role3");  
    }   

    (2)基于资源的访问控制(显式角色)

      在ini配置文件配置用户拥有的角色及角色-权限关系(shiro-permission.ini)

    [users]  
    zhang=123,role1,role2  
    wang=123,role1  
    [roles]  
    role1=user:create,user:update  
    role2=user:create,user:delete   

      规则:“用户名=密码,角色1,角色2”“角色=权限1,权限2”,即首先根据用户名找到角色,然后根据角色再找到权限;即角色是权限集合;Shiro同样不进行权限的维护,需要我们通过Realm返回相应的权限信息。只需要维护“用户——角色”之间的关系即可。

      测试用例

    @Test  
    public void testIsPermitted() {  
        login("classpath:shiro-permission.ini", "zhang", "123");  
        //判断拥有权限:user:create  
        Assert.assertTrue(subject().isPermitted("user:create"));  
        //判断拥有权限:user:update and user:delete  
        Assert.assertTrue(subject().isPermittedAll("user:update", "user:delete"));  
        //判断没有权限:user:view  
        Assert.assertFalse(subject().isPermitted("user:view"));  
    }   
    @Test(expected = UnauthorizedException.class)  
    public void testCheckPermission () {  
        login("classpath:shiro-permission.ini", "zhang", "123");  
        //断言拥有权限:user:create  
        subject().checkPermission("user:create");  
        //断言拥有权限:user:delete and user:update  
        subject().checkPermissions("user:delete", "user:update");  
        //断言拥有权限:user:view 失败抛出异常  
        subject().checkPermissions("user:view");  
    }   

      失败的情况下会抛出 UnauthorizedException 异常.

      Subject subject = SecurityUtils.getSubject();

    案例笔记:

    权限数据库设计(PS:尽量不要涉及外键,管理起来有时候会比较麻烦):

    表:User(用户) Role(角色) UserRole(用户角色对应关系) Resource(资源) RoleResource(角色资源)

    User(id username userpwd nickname status)   //status标注用户账号是否停用或者被锁定;
    
    Role(id name)
    
    Resource(id name permission url)
    
    RoleResource(id roleId resId)
    
    UserRole(id userId roleId)

    Dao设计:继承IBaseDao

    IuserDao: 用户接口

    public list<User> listAllUsers();//查询所有用户
    
    public list<User> listUsersByRole(int roleId);//根据角色取出所有用户
    
    public User loadByUserName(string username);//根据用户得到用户

    IRoleDao: 角色接口

    public list<Role> listRoles();//查询所有的角色
    
    public list<Role> listUserRole();//查询某个用户所有的角色
    
    pubic UserRole loadUserRole(int userId,int RoleId);
    
    public void addUserRole(int userId,int RoleId);
    
    public void deleteUserRole(int UserId,int RoleId);
    
    public void deleteUserRole(int UserId);//删除某个用户的所有角色
    
    public List<Resource> listRoleResources(int roleId);//根据角色Id添加角色可以访问的资源
    
    public void addRoleResource(int RoleId,int resId);
    
    public void deleteRoleResource(int roleId,int resId);
    
    public RoleResource loadRoleResource(int roleId,int resId); //获取角色资源对象

    IResourceDao: 资源接口

    public List<Resource> listResource();

     02 实现Service层:

    IUserService     IRoleService   IRoleResource

    shiro.Kit包下面添加密码加密函数  

    static String md5(String password,String salt) {
    
     String p = null;
    
       p = new Md5Hash(password,salt).toHex();
    
       return P;
    
    }

    03 Junit 实现对Service层测试;

  • 相关阅读:
    随笔
    随笔
    第一个存储过程
    mysql 存储过程
    join
    随笔
    玩家注册登录
    mysql 存储二进制数据
    mysql学习
    socket listen/accept
  • 原文地址:https://www.cnblogs.com/QQ931697811/p/6406783.html
Copyright © 2020-2023  润新知