Shiro第一个程序:官方快速入门程序Qucickstart详解教程



一、下载解压

首先下载Shirohttps://github.com/apache/shiro
image-20201013230542649
下载完成后解压
image-20201013230605248



二、第一个Shiro程序

接下来我们根据官方文档编写第一个Shiro程序

官方文档:

新建一个普通的maven项目,删除src目录,然后再新建一个modulehello-shiro

根据官方文档:
image-20201013231730485
接下来进入到samples/quickstart目录,可以看到src目录和对应的pom.xml,这就是为了我们快速入门shiro一个maven项目的源代码,接下来我们将该项目对应的代码拷贝到我们自己创建的项目中
image-20201013230913910


1. 导入依赖

复制pom.xml中的dependency依赖到自己创建的项目的pom.xml中

<dependencies>
	<dependency>
    	<groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
    </dependency>
    <!-- configure logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

然后替换为有版本号的依赖,注意删除scope属性!! 否则测试结果无法成功

<dependencies>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.6.0</version>
    </dependency>
    <!-- configure logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>2.0.0-alpha1</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>2.0.0-alpha1</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
</dependencies>

2. 配置shiro配置文件

quickstart\src\main\resources下的log4j.propertiesshiro.ini拷贝到项目的resources目录下
image-20201013232245234
其中.ini文件并没有高亮,IDEA提示我们安装插件,我们点击install plugins安装即可

然后点击OK即可
image-20201013232455343
完成后即有高亮显示


3. Quickstart.java

quickstart\src\main\java目录下的Quickstart.java到自己项目的java目录下

image-20201014001721584
发现爆红,这时候将爆红的两个import删除即可


4. 启动测试

运行Quickstart的main方法

发现打印了一些日志信息,到此我们第一shiro程序quickstart就搞定了
image-20201017181227534



三、shiro.ini分析

我们来分析一下官方提供的快速入门的INI Realm配置文件,可以分为两个部分

  • 设置用户名以及对应的角色
  • 设置角色对应的权限
#快速入门INI Realm配置

#用户及其分配的角色
[users]
#用户root 密码:secret 角色:admin
root = secret, admin
#用户guest 密码:guest 角色:guest
guest = guest, guest
#用户presidentskroob 密码:12345 角色:president
presidentskroob = 12345, president
#用户darkhelmet 密码:ludicrousspeed 角色:darklord和schwartz
darkhelmet = ludicrousspeed, darklord, schwartz
#用户lonestarr 密码:vespa 角色:goodguy和schwartz
lonestarr = vespa, goodguy, schwartz

# 具有分配权限的角色
[roles]
#admin角色具有所有权限,用通配符*表示
admin = *
#schwartz角色通过lightsaber:*获得有所有权限
schwartz = lightsaber:*
#goodguy角色通过eagle5(特定实例的ID)可以dirve(动作)Winnebago(类型)
goodguy = winnebago:drive:eagle5


四、Quickstart.java源码分析

我们来分析以下官方提供的Quickstart.java

1. 使用指定类初始化日志对象

private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);

通过获得日志对象,打印后续的日志信息

2. 通过.ini文件创建SecurityManager实例

//创建带有realms,users,roles和permissions配置的Shiro SecurityManager的最简单方法是使用简单的ini配置
//我们将使用可提取.ini文件(在类路径的根目录下使用shiro.ini文件)的工厂返回一个SecurityManager实例
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();

//对于这个简单的示例快速入门,请使SecurityManager作为JVM单例访问。
//大多数应用程序都不会这样做,而在webapps会依靠其容器配置或web.xml进行使用
SecurityUtils.setSecurityManager(securityManager);

到此,基本的shiro环境已经搭建完成,接下来进行的是自己的一些操作

3. 获取当前执行的用户subject

//获取当前执行的用户subject
Subject currentUser = SecurityUtils.getSubject();

4. 通过当前用户得到session存取值并打印

//通过当前用户得到session,使用Session做一些事情(不需要Web或EJB容器)
Session session = currentUser.getSession();
session.setAttribute("someKey", "aValue");//设置session其中的值
String value = (String) session.getAttribute("someKey");//获取session中值
if (value.equals("aValue")) {
    
    
    log.info("Retrieved the correct value! [" + value + "]");//通过日志打印session的值
}

5. 测试当前用户是否被认证

//测试当前用户是否被认证
if (!currentUser.isAuthenticated()) {
    
    //如果没有被认证
    UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");//生成一个Token令牌,随机设置
    token.setRememberMe(true);//设置记住我
    try {
    
    
        currentUser.login(token);//执行登录操作
    } catch (UnknownAccountException uae) {
    
    //未知的账户
        log.info("There is no user with username of " + token.getPrincipal());
    } catch (IncorrectCredentialsException ice) {
    
    //证书不正确
        log.info("Password for account " + token.getPrincipal() + " was incorrect!");
    } catch (LockedAccountException lae) {
    
    //用户被锁定
        log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                "Please contact your administrator to unlock it.");
    }
    //...还可以捕获更多异常(也许是针对您的应用程序的自定义异常)
    catch (AuthenticationException ae) {
    
    
        //意外状况?错误?
    }
}

6. 打印当前用户的主要身份信息

//打印当前用户的主要身份信息(本案例中是用户名)
log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

7. 判断当前用户角色

//测试角色
if (currentUser.hasRole("schwartz")) {
    
    
    log.info("May the Schwartz be with you!");
} else {
    
    
    log.info("Hello, mere mortal.");
}

8. 判断当前用户的权限

//测试权限(不是实例级别:粗粒度)
if (currentUser.isPermitted("lightsaber:wield")) {
    
    
    log.info("You may use a lightsaber ring.  Use it wisely.");
} else {
    
    
    log.info("Sorry, lightsaber rings are for schwartz masters only.");
}

//(非常强大的)实例级别权限:细粒度
if (currentUser.isPermitted("winnebago:drive:eagle5")) {
    
    
    log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
            "Here are the keys - have fun!");
} else {
    
    
    log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}

9. 注销结束系统

//注销
currentUser.logout();

//结束系统
System.exit(0);

完整含注释代码:

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


//简单的快速入门应用程序,显示了如何使用Shiro的API
public class Quickstart {
    
    

    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {
    
    
        //创建带有realms,users,roles和permissions配置的Shiro SecurityManager的最简单方法是使用简单的ini配置
        //我们将使用可提取.ini文件(在类路径的根目录下使用shiro.ini文件)的工厂返回一个SecurityManager实例
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();

        //对于这个简单的示例快速入门,请使SecurityManager作为JVM单例访问。
        //大多数应用程序都不会这样做,而在webapps会依靠其容器配置或web.xml进行使用
        SecurityUtils.setSecurityManager(securityManager);

        //现在已经建立了一个简单的Shiro环境,接下来可以进行一些操作

        //获取当前执行的用户subject
        Subject currentUser = SecurityUtils.getSubject();

        //通过当前用户得到session,使用Session做一些事情(不需要Web或EJB容器)
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");//设置值
        String value = (String) session.getAttribute("someKey");//获取值
        if (value.equals("aValue")) {
    
    
            log.info("Retrieved the correct value! [" + value + "]");
        }

        //让我们登录当前用户,以便我们可以检查角色和权限
        //测试当前用户是否被认证
        if (!currentUser.isAuthenticated()) {
    
    //如果没有被认证
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");//生成一个Token令牌,随机设置
            token.setRememberMe(true);//设置记住我
            try {
    
    
                currentUser.login(token);//执行登录操作
            } catch (UnknownAccountException uae) {
    
    //未知的账户
                log.info("There is no user with username of " + token.getPrincipal());
            } catch (IncorrectCredentialsException ice) {
    
    //证书不正确
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            } catch (LockedAccountException lae) {
    
    //用户被锁定
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            //...还可以捕获更多异常(也许是针对您的应用程序的自定义异常)
            catch (AuthenticationException ae) {
    
    
                //意外状况?错误?
            }
        }

        //打印当前用户的主要身份信息(本案例中是用户名)
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //测试角色
        if (currentUser.hasRole("schwartz")) {
    
    
            log.info("May the Schwartz be with you!");
        } else {
    
    
            log.info("Hello, mere mortal.");
        }

        //测试权限(不是实例级别:粗粒度)
        if (currentUser.isPermitted("lightsaber:wield")) {
    
    
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
    
    
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        //(非常强大的)实例级别权限:细粒度
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
    
    
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
    
    
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        //注销
        currentUser.logout();

        //结束系统
        System.exit(0);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45173404/article/details/109289607