Shiro入门一:基于java项目,初识Shiro

在看了两天的《跟我学Shiro》之后,针对大佬的博客源码来梳理一下对Shiro的简单理解。

《跟我学Shiro》pdf上传两次都失败了,上传成功之后再贴出来分享给需要的同学。

首先是shiro-permission.ini文件的配置:
里面包含了用户和权限

[users]

zhangsan=123,role1,role2
wang=123,role2

#权限
[roles]
#角色role1对资源user拥有createupdate权限
role1=user:create,user:update
role2=user:create,user:delete
role3=user:create

下面是测试代码:

package com.hust.shiro.authorization;

import java.util.Arrays;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
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;

/**
 * 授权测试
 * 
 * @author Administrator
 */
public class Authorization {

    // 角色授权、资源授权测试
    @Test
    public void testAuthorization() {

        // 创建SecurityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");

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

        // 将SecurityManager设置到系统中
        SecurityUtils.setSecurityManager(securityManager);

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

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

        // 执行认证
        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            System.out.println("用户名未注册");
        } catch (IncorrectCredentialsException e) {
            System.out.println("密码不正确");
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

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

        // 认证通过后执行授权

        // 基于角色的授权(在配置文件中)   zhang=123,role1,role2 
        //boolean isHasRole = subject.hasRole("role1"); 
        //System.out.println("isHasRole:" + isHasRole);
        if (subject.hasRole("role1")){
            System.out.println("zhangsan拥有role1");
        }else{
            System.out.println("zhangsan没有role1");
        }

         // 判断拥有角色:role1 and role2 
        boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2"));
        System.out.println("hasAllRoles:" + hasAllRoles);

        // 判断拥有角色:role1 不同的是当判断为假时抛出AuthorizationException异常
        try {
            subject.checkRole("role1");
        } catch (AuthorizationException e) {
            e.printStackTrace();
        }

        // 基于资源的授权
        boolean isPermitted = subject.isPermitted("user:create");
        System.out.println("isPermitted:" + isPermitted);

        //使用check方法判断授权,如果授权不通过抛出异常
        try {
            subject.checkPermission("user:create");
        } catch (AuthorizationException e) {
            e.printStackTrace();
        }
    }
}

运行之后可以看到控制台打印的信息,可以看到是如何一步一步读取这个ini配置文件的。
这里写图片描述

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

Shiro 提供的 checkRole/checkRoleshasRole/hasAllRoles 不同的地方是它在判断为假的情 况下会抛出 UnauthorizedException 异常

另外一种就是 基于角色的访问控制(即隐式角色)叫做粗粒度判断,这种方式的缺点就是如果很多地方进 行了角色判断,但是有一天不需要了那么就需要修改相应代码把所有相关的地方进行删除; 这就是粗粒度造成的问题

Shiro 提供了 isPermittedisPermittedAll 用于判断用户是否拥有某个权限或所有权限,也 没有提供如 isPermittedAny 用于判断拥有某一个权限的接口。

Shiro 提供的checkPermissioncheckPermissions 但是失败的情况下会抛出 UnauthorizedException 异常.

基于资源的访问控制(显示角色),也可以叫基于权限的访问控制(细粒度判断),这种方式的一般规则是“资源标识符:操作”,即是资源级别的粒度;这种方式的好处就是如果 要修改基本都是一个资源级别的修改,不会对其他模块代码产生影响,粒度小。但是实现 起来可能稍微复杂点,需要维护“用户——角色,角色——权限(资源:操作)”之间的 关系

用户可以自己定义Realm

shiro-realm.ini配置:

[main]

#自定义realm
customRealm=com.hust.shiro.realm.CustomRealm
#将realm设置到SecurityManager,相当于注入
securityManager.realm=$customRealm

自定义Realm:

package com.hust.shiro.realm;
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;

public class CustomRealm extends AuthorizingRealm {

    @Override
    public void setName(String name) {
        // TODO Auto-generated method stub
        super.setName("customRealm");
    }

    // 用于认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //第一步就是从token中取用户身份信息
        String userCode = (String) token.getPrincipal();

        //如果查询不到返回null
        //模拟在数据库中找不到用户
        if (!userCode.equals("zhangsansan")) {
            return null;
        }

        //第二步根据用户输入的userCode从数据库查询
        String password = "111111";


        //如果查询到返回AuthenticationInfo

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



        return simpleAuthenticationInfo;
    }

    // 用于授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        //principals获取主身份信息
        //将getPrimaryPrincipal方法返回值强转为真实身份类型
        String userCode = (String) principals.getPrimaryPrincipal();

        //根据身份信息获取权限信息
        //模拟数据
        List<String> permissions = new ArrayList<String>();
        permissions.add("user:create");
        permissions.add("items:update");

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

        return simpleAuthorizationInfo;
    }

}

测试方法:

// 自定义realm
    @Test
    public void testCustomRealm() {

        // 创建securityManager工厂,通过ini文件创建securityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");

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

        // 将securityManager设置当前的运行环境中
        SecurityUtils.setSecurityManager(securityManager);

        // SecurityUtils里面创建一个subject
        Subject subject = SecurityUtils.getSubject();

        // 在认证提交前要准备token(令牌)
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsansan", "111111");

        // 执行认证提交
        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            System.out.println("用户名未注册");
        } catch (IncorrectCredentialsException e) {
            System.out.println("密码不正确");
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

        // 是否认证通过
        boolean isAuthenticated = subject.isAuthenticated();

        System.out.println("是否认证通过: " + isAuthenticated);

        // 判断权限
        boolean isPermission = subject.isPermitted("user:create");
        System.out.println("isPermission:" + isPermission);
        // 退出操作
        subject.logout();

        // 是否认证通过
        isAuthenticated = subject.isAuthenticated();
        System.out.println("退出后是否认证通过: " + isAuthenticated);
    }

使用md5加密处理:
shiro-realm-md5.ini

[main]
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数
credentialsMatcher.hashIterations=1

#自定义realm
customRealm=com.hust.shiro.realm.CustomRealmMD5
customRealm.credentialsMatcher=$credentialsMatcher
#将realm设置到SecurityManager,相当于注入
securityManager.realms=$customRealm

CustomRealmMD5.java

package com.hust.shiro.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 CustomRealmMD5 extends AuthorizingRealm {

    @Override
    public void setName(String name) {
        super.setName("customRealmMD5");
    }

    // 用于认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //第一步就是从token中取用户身份信息
        String userCode = (String) token.getPrincipal();

        //如果查询不到返回null
        //模拟在数据库中找不到用户
        if (!userCode.equals("zhangsansan")) {
            return null;
        }

        //第二步根据用户输入的userCode从数据库查询
        String password = "98cd6f146bdec65a48dedc505aaf2b80";
        String salt = "sadsgg";

        //如果查询到返回AuthenticationInfo

        SimpleAuthenticationInfo simpleAuthenticationInfo = 
                new SimpleAuthenticationInfo(userCode, password, ByteSource.Util.bytes(salt),this.getName());

        return simpleAuthenticationInfo;
    }

    // 用于授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

}

测试代码:

// 自定义realm实现散列匹配
    @Test
    public void testCustomRealmMD5() {

        // 创建securityManager工厂,通过ini文件创建securityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm-md5.ini");

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

        // 将securityManager设置当前的运行环境中
        SecurityUtils.setSecurityManager(securityManager);

        // SecurityUtils里面创建一个subject
        Subject subject = SecurityUtils.getSubject();

        // 在认证提交前要准备token(令牌)
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsansan", "123456");

        // 执行认证提交
        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            System.out.println("用户名未注册");
        } catch (IncorrectCredentialsException e) {
            System.out.println("密码不正确");
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }

        // 是否认证通过
        boolean isAuthenticated = subject.isAuthenticated();

        System.out.println("是否认证通过: " + isAuthenticated);

        // 判断权限
        boolean isPermission = subject.isPermitted("user:create");
        System.out.println("isPermission:" + isPermission);

        // 退出操作
        subject.logout();

        // 是否认证通过
        isAuthenticated = subject.isAuthenticated();
        System.out.println("是否认证通过: " + isAuthenticated);



    }
智慧旅游解决方案利用云计算、物联网和移动互联网技术,通过便携终端设备,实现对旅游资源、经济、活动和旅游者信息的智能感知和发布。这种技术的应用旨在提升游客在旅游各个环节的体验,使他们能够轻松获取信息、规划行程、预订票务和安排食宿。智慧旅游平台为旅游管理部门、企业和游客提供服务,包括政策发布、行政管理、景区安全、游客流量统计分析、投诉反馈等。此外,平台还提供广告促销、库存信息、景点介绍、电子门票、社交互动等功能。 智慧旅游的建设规划得到了国家政策的支持,如《国家中长期科技发展规划纲要》和国务院的《关于加快发展旅游业的意见》,这些政策强调了旅游信息服务平台的建设和信息化服务的重要性。随着技术的成熟和政策环境的优化,智慧旅游的时机已经到来。 智慧旅游平台采用SaaS、PaaS和IaaS等云服务模式,提供简化的软件开发、测试和部署环境,实现资源的按需配置和快速部署。这些服务模式支持旅游企业、消费者和管理部门开发高性能、高可扩展的应用服务。平台还整合了旅游信息资源,提供了丰富的旅游产品创意平台和统一的旅游综合信息库。 智慧旅游融合应用面向游客和景区景点主管机构,提供无线城市门户、智能导游、智能门票及优惠券、景区综合安防、车辆及停车场管理等服务。这些应用通过物联网和云计算技术,实现了旅游服务的智能化、个性化和协同化,提高了旅游服务的自由度和信息共享的动态性。 智慧旅游的发展标志着旅游信息化建设的智能化和应用多样化趋势,多种技术和应用交叉渗透至旅游行业的各个方面,预示着全面的智慧旅游时代已经到来。智慧旅游不仅提升了游客的旅游体验,也为旅游管理和服务提供了高效的技术支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值