Shiro入门10:自定义Realm进行授权

需求:

    |---前一个的程序通过shiro-permission.ini作为数据源对权限信息进行静态配置,实际开发中从数据库中获取权限数据
        就需要自定义realm,由Realm从数据库查询权限数据。
    |---Realm根据用户身份查询权限数据,将权限数据返回给Authorizer(授权器)
    |
    |---自定义Realm【实现AuthorizingRealm】
        |---在原来自定义的Realm中修改doGetAuthorizationInfo




配置shiro-realm.ini文件【跟上面一样,配置realm到securityManager中】

Edit
[main]

#自定义realm
customRealm = cn.marer.shiro.realm.CustomRealm

#将realm设置到securityManager,相当于Spring中的注入
securityManager.realms = $customRealm



此文老猫原创,转载请加本文连接:http://blog.csdn.net/nthack5730/article/details/51019516

更多有关老猫的文章:http://blog.csdn.net/nthack5730



自定义Realm测试:

     |---需要注意的是:下面方法中部分代码代替了数据库的查询过程
     |---重写实现方法:doGetAuthorizationInfo(PrincipalCollection principals)

import java.util.ArrayList;
import java.util.List;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * 自定义Realm
 * @author CatScan
 *
 */

public class CustomRealm extends AuthorizingRealm{
    final String realmName="customRealm";


    //设置realmName
    @Override
    public void setName(String name) {
        super.setName(realmName);
    }



    //用于认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token)
 throws AuthenticationException 
{

        // 第一步从token中取出用户发送过来的身份信息
        String userCode = (String) token.getPrincipal();

        //第二步根据用户输入的帐号从数据库查询
        //...
        String pwd = "11111";


        //如果查询不到返回null
        //如果查询到,返回认证信息:AuthenticationInfo

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userCode, pwd, this.getName());

        return simpleAuthenticationInfo;
    }



    //用于授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //从principals获取主身份信息
        //将getPrimaryPrincipal()返回的值强制转换为真实身份信息【在上边的doGetAuthenticationInfo()认证通过填充到SimpleAuthenticationInfo中的身份信息】
        String userCode = (String) principals.getPrimaryPrincipal();

        //根据身份信息获取权限信息
        //先链接数据库。。。
        //模拟从数据库获取数据
        List<String> permissions = new ArrayList<String>();
        permissions.add("user:create");//用户的创建权限
        permissions.add("user:update");//用户的修改
        permissions.add("item:add");//商品的添加权限
        //....等等权限

        //查到权限数据,返回
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        //将List里面的权限填充进去
        simpleAuthorizationInfo.addStringPermissions(permissions);

        return simpleAuthorizationInfo;

    }
}




此文老猫原创,转载请加本文连接:http://blog.csdn.net/nthack5730/article/details/51019516

更多有关老猫的文章:http://blog.csdn.net/nthack5730



测试类:测试自定义Realm授权功能

     |---主要是要注意好是否已经在上面的配置文件中绑定了测试的Realm

Edit

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

public class AuthorizationTest {
    //===========================================
    // 自定义Realm进行授权测试:角色授权、资源授权
    //===========================================
    @Test
    public void testAuthorizationCustomRealm(){
        //创建一个SecurityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");

        //创建SecurityManager 
        SecurityManager sm = factory.getInstance();

        //将SecurityManager设置到系统运行环境,和Spring整合后将SecurityManager配置到Spring容器中,一般单例管理
        SecurityUtils.setSecurityManager(sm);

        //创建Subject
        Subject subject = SecurityUtils.getSubject();

        //创建token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan""11111");

        //执行认证
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }

        System.out.println("认证状态:" + subject.isAuthenticated());


        //认证通过后执行授权

        //===========================================
        // 基于角色授权
        //===========================================
        //hasRole方法传入的是角色标识
//      boolean isHasRole = subject.hasRole("role1");
//      System.out.println("正确角色,角色有权限--->" + isHasRole);

//      //传入错误的角色
//      boolean isHasRole2 = subject.hasRole("role12");
//      System.out.println("错误角色,角色有权限--->" + isHasRole2);

//      //判断多个角色
//      boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2"));
//      System.out.println("多个角色判断--->" + hasAllRoles);

        //使用check方法进行授权,如果不通过,会抛出异常
//      try {
//          subject.checkRole("role12");
//      } catch (AuthorizationException e) {
//          // TODO 自动生成的 catch 块
//          e.printStackTrace();
//      }


        //===========================================
        // 基于资源授权
        //===========================================
        //调用isPermitted(),就会调用CustomRealm从数据库查数据权限数据
        //isPermitted()传入权限标识符,判断user:create:1是否在CustomRealm查询到权限数据之内
        boolean isPermited = subject.isPermitted("user:create:1");
        System.out.println("资源有权限,单个权限判断--->" + isPermited);

        //传入的是资源标识符,多个权限判断
        boolean isPermitedAll = subject.isPermittedAll("user:create","user:update","user:delete");
        System.out.println("资源有权限,多个权限判断--->" + isPermitedAll);

        //资源权限也支持check,如果不通过,也会抛异常
        try {
            subject.checkPermission("item:add");
        } catch (AuthorizationException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
            System.out.println(e.toString());
        }


        subject.getPrincipal();

    }//method
}




授权的流程的总结:


  1. subject进行授权,调用方法:isPermitted("permission串");或isAllPermitted();【查看permission串在不在权限范围内】
  2. 由SecurityManager执行授权,最终通过ModularRealmAuthorizer执行授权
  3. ModularRealmAuthorizer执行Realm【上面自定义的CustomRealm】从数据库查询权限数据
  4. 【调用Realm的:doGetAuthorizationInfo(PrincipalCollection principals) 】
  5. Realm从数据库查询权限数据,返回ModularRealmAuthorizer【这个词和认证的方法容易混淆,记得注意区分
  6.  ModularRealmAuthorizer进行权限数据的匹配:调用PermissionResolver进行权限比对。
  7. 如果比对后:isPermitted(中的"permission串"),在Realm查询到的权限数据中,说明授权通过【用户访问的Permission串具有权限;否则,没有权限,抛出异常】

此文老猫原创,转载请加本文连接:http://blog.csdn.net/nthack5730/article/details/51019516

更多有关老猫的文章:http://blog.csdn.net/nthack5730




  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值