shrio教程初级(五)shiro基础(授权)-阿里云开发者社区

开发者社区> 安全> 正文

shrio教程初级(五)shiro基础(授权)

简介: 一、前言 回忆过去,shiro的认证忘不了: 0:通过securityFactory建立securityManager,加入securityUtil加入环境 1、subject(主体...

一、前言

回忆过去,shiro的认证忘不了:

0:通过securityFactory建立securityManager,加入securityUtil加入环境

1、subject(主体)请求认证,调用login(token)

2、securityManager开始认证

3、securityManager通过ModularRealmAuthenticator进行认证

4、ModularRealmAuthenticator将token传统给realm,realm根据token从数据源(库)查询用户信息的身份和凭证(用户名与密码)。

5、realm查询不到返回空(用户不存在异常),如果凭证错误,返回凭证错误。否则返回正确的AuthenticationInfo(认证信息)

二、shrio权限授权

权限授权验证,一样是四个步骤,写ini文件-----加载ini----认证用户----权限验证,请注意任何认证之后才验证权限,是一般的思路不要忘记了。

2.1 编写ini文件

shiro-permission.ini
#用户
[users]
#用户zhang的密码是123,此用户具有role1和role2两个角色
ycy=111,role1,role2
ycy2=111,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

解读:user:create为我们的权限标示,表达:资源:操作:实例。因为我们这里默认是有实例。其实应该是:user:create:*  当然也可以真的某一个实例:user:create:01
    ycy=111,role1 逗号第一位为我们的凭证(密码),后面为角色。

2.2编写测试程序

编写权限认证不要忘记用户认证
程序里面只多了个permitted(权限)或者hasRole(角色),其他的与我们用户认证是一样的。

package com.ycy.test;

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

import java.util.ArrayList;
import java.util.Arrays;


/**
 * Created by Administrator on 2015/10/16 0016.
 * 权限授权
 */
public class authorizationTest {
    @Test
    public void testAuthorization(){
        //创建securityManager工厂
        Factory<SecurityManager> securityManagerFactory=new IniSecurityManagerFactory("classpath:shiro-permission.ini");

        //获取security
        SecurityManager securityManager=securityManagerFactory.getInstance();

        //蒋securityManager加入运行坏境
        SecurityUtils.setSecurityManager(securityManager);

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

        //创建用户令牌
        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken("ycy","111");

        //先认证
        subject.login(usernamePasswordToken);
        System.out.println("用户时候通过认证:" + subject.isAuthenticated());

        //再权限授权验证(单个)
         Boolean isPermittedOne=  subject.isPermitted("user:create");
        System.out.println("单个权限认证:"+isPermittedOne);
        //授权验证权限(多个)
        Boolean isPermittedAll=subject.isPermittedAll("user:create", "user:update");
        System.out.println("多个权限认证:" + isPermittedOne);


        //另外也可以角色验证权限(不建议)
        Boolean ishasRole=   subject.hasRole("role1");
        Boolean ishasRoleAll=  subject.hasAllRoles(Arrays.asList("role1","role2"));
        System.out.println("单个角色验证:"+ishasRole+"|多个角色验证"+ishasRoleAll);
    }
}


三、shrio权限授权(自定义realm)

1、自定义realm

package com.ycy.realm;

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;

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

/**
 * Created by Administrator on 2015/10/15 0015.
 * 自定义数据源
 */
public class CustomRealm extends AuthorizingRealm{

    //用户认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
       //authenticationToken为用户输入信息
        String userCode=(String)authenticationToken.getPrincipal();
        //模拟数据库操作查询用户
        if(!userCode.equals("ycy")){
            return null;
        }
        //查询密码为111
        String password="111";

        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(userCode,password,"customRealm");

        return info;
    }
    //用户授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
         //获取身份信息Principal
        //这里的值跟我们用户认证的时候SimpleAuthenticationInfo一样
        String usercode=(String)principalCollection.getPrimaryPrincipal();
        //查询数据库。。。。
        //模拟查询到数据
        List<String> permission=new ArrayList<String>();
        permission.add("user:create");
        permission.add("items:add");
        //..................
        //查询全选数据,返回授权信息
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
        //增加权限信息
        simpleAuthorizationInfo.addStringPermissions(permission);
        return simpleAuthorizationInfo;
    }


}

2、编写ini程序

#用户信息配置
[main]
#自定义realm
cutomRealm= com.ycy.realm.CustomRealm
#自定义realm注入到securityManager中(标签语言)
securityManager.realms=$cutomRealm


3、测试自定义授权

//自定义权限realm信息
        //用户登录和退出(自定义realm)
        @Test
        public void testCustomRealm(){
            //创建一个securityManager 通过ini文件创建
            Factory<SecurityManager> securityManagerFactory=new IniSecurityManagerFactory("classpath:shrio-realm.ini");
    //        XMLSecurityManager
            //创建SecurityManager
            SecurityManager securityManager=  securityManagerFactory.getInstance();
            //将SecurityManager创建到生成环境中
            SecurityUtils.setSecurityManager(securityManager);
            //从SecurityUtils 构建一个subject
            org.apache.shiro.subject.Subject subject=SecurityUtils.getSubject();
            //认证提交认证token
            UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken("ycy","111");
            //执行认证提交认证
            try {
                subject.login(usernamePasswordToken);
            }catch(AuthenticationException ex){
                ex.printStackTrace();
            }
            System.out.println("是否通过认证:" + subject.isAuthenticated());
            //授权。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
            //单个权限授权
            boolean ispermitted=subject.isPermitted("user:create");
            //多个权限授权
            boolean ispermittedAll=subject.isPermittedAll("user:create","items:add");
    
            System.out.println("单个授权:"+ispermitted+"|多个授权"+ispermittedAll);
            //退出
            subject.logout();
        }

四、授权流程总结

1、对subject进行授权,调用的方法ispermitted("permission");括号里面为权限串:user:create
2、securityManager执行授权,通过ModularRealmAuthorize执行授权
3、ModularRealmAuthorizer执行realm从数据源查询数据 (调用doGetAuthorizationInfo)
4、ModularRealmAuthorizer(授权器)调用PermissionResolve(权限解析器)进行全新串对比
5、对比之后,ispermitted中的permission串与realm查询的串对比,无权限则抛出异常。有权限则通过授权。

注意:这个授权器modularRealmAuthorize跟我们的ModularRealmAuthenticator很像,做的事情也是从realm查询对比,但是功能不一样的:
ModularRealmAuthorizer 返回:SimpleAuthenticationInfo   认证信息
ModularRealmAuthenticator返回:simpleAuthorizationInfo 权限信息



 

版权声明:本文首发在云栖社区,遵循云栖社区版权声明:本文内容由互联网用户自发贡献,版权归用户作者所有,云栖社区不为本文内容承担相关法律责任。云栖社区已升级为阿里云开发者社区。如果您发现本文中有涉嫌抄袭的内容,欢迎发送邮件至:developer2020@service.aliyun.com 进行举报,并提供相关证据,一经查实,阿里云开发者社区将协助删除涉嫌侵权内容。

分享:
+ 订阅

云安全开发者的大本营

其他文章