目录
一、下载解压
首先下载Shiro
:https://github.com/apache/shiro
下载完成后解压
二、第一个Shiro程序
接下来我们根据官方文档编写第一个Shiro程序
官方文档:
关于Apache Shiro的10分钟教程:http://shiro.apache.org/10-minute-tutorial.html
您的第一个Apache Shiro应用程序:http://shiro.apache.org/tutorial.html
新建一个普通的maven项目,删除src
目录,然后再新建一个module
:hello-shiro
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u8g38uOo-1650609133623)(https://gitee.com/zhong_siru/images/raw/master//img/image-20201013231218621.png)]
根据官方文档:
接下来进入到samples/quickstart
目录,可以看到src目录和对应的pom.xml,这就是为了我们快速入门shiro一个maven项目的源代码,接下来我们将该项目对应的代码拷贝到我们自己创建的项目中
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配置文件
将quickstartsrcmain esources
下的log4j.properties
和shiro.ini
拷贝到项目的resources目录下
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q8BQp9nq-1650609133624)(https://gitee.com/zhong_siru/images/raw/master//img/image-20201013232245234.png)]
其中.ini
文件并没有高亮,IDEA提示我们安装插件,我们点击install plugins
安装即可
然后点击OK
即可
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3duUPbAx-1650609133625)(https://gitee.com/zhong_siru/images/raw/master//img/image-20201013232455343.png)]
完成后即有高亮显示
3. Quickstart.java
将
quickstartsrcmainjava
目录下的Quickstart.java
到自己项目的java目录下
发现爆红,这时候将爆红的两个import
删除即可
4. 启动测试
运行
Quickstart
的main方法
发现打印了一些日志信息,到此我们第一shiro程序quickstart就搞定了
三、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);
}
}
}