shiro安全权限框架

本文详细介绍了Apache Shiro框架的认证和授权过程。首先,讲解了认证的关键对象,包括Subject、Principal和credential,并通过示例展示了简单的认证实现和自定义Realm的创建。接着,探讨了授权中的关键对象和授权方式,包括RBAC模型。最后,提供了自定义Realm的授权实现和权限字符串规则的示例代码。文章内容深入浅出,有助于理解Shiro的认证授权机制。
摘要由CSDN通过智能技术生成

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
官方网站:http://shiro.apache.org/

一、shiro中的认证

1、认证中的关键对象

  • Subject:主体
    访问系统的用户,主体可以是用户、程序等,进行认证的都被称为主体。
  • Principal:身份信息
    是主体进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份。
  • credential:凭证信息
    是只有主体自己知道的安全信息,如密码、证书等。

2、简单认证的开发

创建项目并引入依赖。

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

在resources中引入shiro配置文件,命名随意,后缀必须以.ini结尾。(例如:shiro.ini)

[users]
yzs=123456

创建测试认证类

package com.yzs;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;

public class TestAuthenticator {

    public static void main(String[] args) {
        //1、创建安全管理器对象
        DefaultSecurityManager securityManager=new DefaultSecurityManager();

        //2、给安全管理器设置realms
        securityManager.setRealm(new IniRealm("classpath:shiro.ini"));

        //3、SecurityUtils 给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);

        //4、关键对象,主体
        Subject subject = SecurityUtils.getSubject();

        //5、创建令牌
        UsernamePasswordToken token=new UsernamePasswordToken("yzs","12345678");
        try{
            System.out.println("认证状态:"+subject.isAuthenticated());
            //用户登录认证
            subject.login(token);
            System.out.println("认证状态:"+subject.isAuthenticated());
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("认证失败:用户名不存在");
        } catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("认证失败:密码错误");
        }
    }
}

3、实现自定义realm

创建自定义realm类

package 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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

public class CustomerRealm extends AuthorizingRealm {
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String principal = (String) authenticationToken.getPrincipal();
        System.out.println(principal);
        if ("zhangsan".equals(principal)){
            return new SimpleAuthenticationInfo(principal,"123",this.getName());
        }
        return null;
    }
}

创建测试类

package com.yzs;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import realm.CustomerRealm;

public class TestAuthenticatorCustomerRealm {
    public static void main(String[] args) {
        //1、创建安全管理器对象
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        //2、给安全管理器设置自定义realm
        securityManager.setRealm(new CustomerRealm());

        //3、SecurityUtils 给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);

        //4、关键对象,主体
        Subject subject = SecurityUtils.getSubject();

        //5、创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123");
        try {
            subject.login(token);
            System.out.println(subject.isAuthenticated());
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("认证失败:用户名不存在");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("认证失败:密码错误");
        }
    }
}

4、使用md5+salt认证

md5认证常用方法

package com.yzs;

import org.apache.shiro.crypto.hash.Md5Hash;

public class TestShiroMd5 {
    public static void main(String[] args) {
        //使用set方法创建
        Md5Hash md5Hash = new Md5Hash();
        md5Hash.setBytes("123".getBytes());
        System.out.println(md5Hash.toHex());

        //使用md5构造方法创建
        Md5Hash md5Hash1 = new Md5Hash("123");
        System.out.println(md5Hash1.toHex());

        //使用md5+salt处理
        Md5Hash md5Hash2 = new Md5Hash("123","X0*7ps");
        System.out.println(md5Hash2.toHex());

        //使用md5+salt+hash散列处理
        Md5Hash md5Hash3 = new Md5Hash("123","X0*7ps",1024);
        System.out.println(md5Hash3.toHex());
    }
}

创建自定义realm类

package 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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

public class CustomerMd5Realm extends AuthorizingRealm {
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String principal = (String) authenticationToken.getPrincipal();
        if ("zhangsan".equals(principal)){
            return new SimpleAuthenticationInfo(principal,
                    "e4f9bf3e0c58f045e62c23c533fcf633",
                    ByteSource.Util.bytes("X0*7ps"),
                    this.getName());
        }
        return null;
    }
}

创建测试类

package com.yzs;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import realm.CustomerMd5Realm;

public class TestCustomerMd5RealmAuthenicator {
    public static void main(String[] args) {
        //1、创建安全管理器对象
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        //2、给安全管理器设置realm
        CustomerMd5Realm realm = new CustomerMd5Realm();
        //3、设置realm使用hash凭证匹配器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //使用算法
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //散列次数
        hashedCredentialsMatcher.setHashIterations(1024);
        realm.setCredentialsMatcher(hashedCredentialsMatcher);
        securityManager.setRealm(realm);

        //4、SecurityUtils 给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);

        //5、关键对象,主体
        Subject subject = SecurityUtils.getSubject();

        //6、创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
        try {
            subject.login(token);
            System.out.println(subject.isAuthenticated());
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("认证失败:用户名不存在");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("认证失败:密码错误");
        }
    }
}

二、shiro中的授权

1、授权中的关键对象

  • Subject:主体
    主体需要访问系统中的资源。
  • Resource:资源
    如系统菜单、页面、按钮、类方法、系统商品信息等。资源包括资源类型和资源实例,比如商品信息为资源类型,类型为to1的商品为资源实例,编号为001的商品信息也属于资源实例。
  • Permission:权限/许可
    规定了主体对资源的操作许可,权限离开资源没有意义,如用户查询权限、用户添加权限、某个类方法的调用权限、编号为001用户的修改权限等,通过权限可知主体对哪些资源都有哪些操作许可。

2、授权方式

  • RBAC基于角色的访问控制(Role-Based Access Control)
  • RBAC基于资源的访问控制(Resource-Based Access Control)

权限字符串规则:资源标识符:操作:资源实例标识符

3、编程实现方式

编程式

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

注解式

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

标签式(适应于jsp页面)

//页面引入shiro标签
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

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

4、简单授权开发

创建自定义realm类

package 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 org.apache.shiro.util.ByteSource;

public class CustomerMd5Realm extends AuthorizingRealm {
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
        System.out.println("身份信息:"+primaryPrincipal);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        //将数据库中查询角色信息赋值给权限对象
        simpleAuthorizationInfo.addRole("admin");
        simpleAuthorizationInfo.addRole("user");

        //将数据库中查询权限信息赋值给权限对象
        simpleAuthorizationInfo.addStringPermission("user:*:*");
        simpleAuthorizationInfo.addStringPermission("product:*:01");
        return simpleAuthorizationInfo;
    }
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String principal = (String) authenticationToken.getPrincipal();
        if ("zhangsan".equals(principal)){
            return new SimpleAuthenticationInfo(principal,
                    "e4f9bf3e0c58f045e62c23c533fcf633",
                    ByteSource.Util.bytes("X0*7ps"),
                    this.getName());
        }
        return null;
    }
}

创建测试类

package com.yzs;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import realm.CustomerMd5Realm;

import java.util.Arrays;

public class TestCustomerMd5RealmAuthenicator {
    public static void main(String[] args) {
        //1、创建安全管理器对象
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        //2、给安全管理器设置realm
        CustomerMd5Realm realm = new CustomerMd5Realm();
        //3、设置realm使用hash凭证匹配器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //使用算法
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        //散列次数
        hashedCredentialsMatcher.setHashIterations(1024);
        realm.setCredentialsMatcher(hashedCredentialsMatcher);
        securityManager.setRealm(realm);

        //4、SecurityUtils 给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);

        //5、关键对象,主体
        Subject subject = SecurityUtils.getSubject();

        //6、创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
        try {
            subject.login(token);
            System.out.println(subject.isAuthenticated());
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("认证失败:用户名不存在");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("认证失败:密码错误");
        }

        //授权
        if (subject.isAuthenticated()){
            //基于单角色权限控制
            System.out.println(subject.hasRole("admin"));

            //基于多角色权限控制
            System.out.println(subject.hasAllRoles(Arrays.asList("admin","user")));

            //是否具有其中一个角色
            boolean[] booleans = subject.hasRoles(Arrays.asList("admin","user","super"));
            for (boolean booleans1:booleans){
                System.out.println(booleans1);
            }

            //基于权限字符串访问控制
            System.out.println(subject.isPermitted("user:*:*"));

            //分别具有哪些权限
            boolean[] permitted = subject.isPermitted("user:*:*", "product:*:01");
            for (boolean b:permitted){
                System.out.println("权限:"+b);
            }

            //同时具有哪些权限
            System.out.println(subject.isPermittedAll("user:*:*","product:update:01"));
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一条代码鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值