之前的缓存redis整合有问题,虽然也可以用但是不能跨域不能sso单点登陆,所以决定一步步来先学最基础的shiro再去整合springboot吧.下面开始入门!
Quickstart.java
1.获取正在执行的用户:
Subject currentUser = SecurityUtils.getSubject();
2.设置属于用户的session:
Session session = currentUser.getSession();
session.setAttribute( "someKey", "aValue" );
该会话是一个特定于shio的实例,它提供了常规httpsession所提供的大部分内容,但也提供了一些额外的好处,还有一个很大的区别:它不需要HTTP环境!
如果在web应用程序中部署,默认情况下会话将基于HttpSession。但是,在非web环境中,比如这个简单的快速入门,Shiro默认情况下会自动使用它的企业会话管理。这意味着您可以在任何层的应用程序中使用相同的API,而不管部署环境如何。
3.上面的Subject实例表示当前用户,但是谁是当前用户呢?嗯,他们是匿名的——也就是说,直到他们至少登录一次。让我们这样做:(证明你是谁)
if ( !currentUser.isAuthenticated() ) {
//没有登陆 会把用户数据封装
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
//记住我功能
token.setRememberMe(true);
//登陆
currentUser.login(token);
}
就是这样!再简单不过了。
但是如果他们的登录尝试失败了呢?你可以捕获各种特定的异常,告诉你到底发生了什么,并允许你处理和相应的反应:
try {
currentUser.login( token );
//login()中传入了用户数据 它会去Realm中验证数据
} catch ( UnknownAccountException uae ) {
//找不到账户
} catch ( IncorrectCredentialsException ice ) {
//密码不匹配
} catch ( LockedAccountException lae ) {
//尝试次数过多
}
... more types exceptions to check if you want ...
} catch ( AuthenticationException ae ) {
//未知其他错误
}
4.现在,我们有了一个登录用户。我们还能做什么?
我们来看看他们是谁:
//print their identifying principal (in this case, a username):
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:weild" ) ) {
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(); //removes all identifying information and invalidates their session too.
这就是在应用程序开发人员级别使用Apache Shiro的核心。虽然有一些相当复杂的东西在幕后进行,使这个工作如此优雅,这就是它的全部。
但是您可能会问自己,“但是谁负责在登录期间获取用户数据(用户名和密码、角色和权限等),以及谁在运行时实际执行这些安全检查?”通过实现Shiro所称的领域并将该领域插入到Shiro的配置中,您可以做到这一点。
然而,如何配置域在很大程度上取决于您自己
(自己配置Realm决定认证规则等)
后面官网给了一个入门项目,按照该项目我自己搞的:
1.准备一个maven项目
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>shiro-first-test</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.1</version>
</dependency>
<!-- 需要一个日志框架来对接门面日志框架.Shiro uses SLF4J for logging. We'll use the 'simple' binding-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.21</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
<!--门面日志-->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.shiro.ini配置在resource下
# -----------------------------------------------------------------------------
# Users and their (optional) assigned roles
# username = password, role1, role2, ..., roleN
#账号 root 密码 secret 角色admin 账号 guest 密码 guest 角色 guest
# -----------------------------------------------------------------------------
[users]
root = secret, admin
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz
# -----------------------------------------------------------------------------
# Roles with assigned permissions
# roleName = perm1, perm2, ..., permN 角色名的权限设置
# -----------------------------------------------------------------------------
[roles]
admin = *
schwartz = lightsaber:*
goodguy = winnebago:drive:eagle5
3.你的测试类
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.session.UnknownSessionException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
public class ShiroTest {
public static void main(String[] args) {
System.out.println ("我的第一个 Apache Shiro Application");
//加载.ini配置文件,并获取工厂(相当于数据库的数据)
Factory<SecurityManager> factory = new IniSecurityManagerFactory ("classpath:shiro.ini");
//获取安全管理者实例(将数据加载给安全管理者)
SecurityManager securityManager = factory.getInstance ( );
//将安全管理者放入全局对象
SecurityUtils.setSecurityManager (securityManager);
//全局对象通过安全管理者生成Subject对象
// get the currently executing user:
Subject currentUser = SecurityUtils.getSubject ( );
// Do some stuff with a Session (no need for a web or EJB container!!!)
Session session = currentUser.getSession ( );
session.setAttribute ("someKey", "aValue");
String value = (String) session.getAttribute ("someKey");
if (value.equals ("aValue")) {
System.out.println ("Retrieved the correct value! [" + value + "]");
}
//没有验证 就去检查角色和权限
// let's login the current user so we can check against roles and permissions:
if (!currentUser.isAuthenticated ( )) {
//封装用户的数据,相当于表单传过来的账号密码
UsernamePasswordToken token = new UsernamePasswordToken ("lonestarr", "vespa");
//记住我功能是否启用
token.setRememberMe (true);
try {
//传入用户数据,之后的工作会交给Realm进行验证账户,密码
currentUser.login (token);
} catch (UnknownAccountException uae) {
//没有这个用户
System.out.println ("There is no user with username of " + token.getPrincipal ( ));
} catch (IncorrectCredentialsException ice) {
//密码不对
System.out.println ("Password for account " + token.getPrincipal ( ) + " was incorrect!");
} catch (LockedAccountException lae) {
//尝试次数过多
System.out.println ("The account for username " + token.getPrincipal ( ) + " is locked. " +
"Please contact your administrator to unlock it.");
}
// ... catch more exceptions here (maybe custom ones specific to your application?
catch (AuthenticationException ae) {
//其他错误
//unexpected condition? error?
}
}
//say who they are:
//print their identifying principal (in this case, a username):
//打印用户名
System.out.println ("User [" + currentUser.getPrincipal ( ) + "] 登陆成功!.");
//test a role:测试是否有schwartz这个角色
if (currentUser.hasRole ("schwartz")) {
System.out.println ("你拥有角色'Schwartz'");
} else {
//普通角色
System.out.println ("Hello, 你不是'schwartz'这个角色");
}
//test a typed permission (not instance-level)测试用户是否有权限lightsaber:wield
if (currentUser.isPermitted ("lightsaber:wield")) {
System.out.println ("你拥有权限,'lightsaber:wield'");
} else {
System.out.println ("抱歉, lightsaber 仅仅 角色为 schwartz 拥有.");
}
//a (very powerful) Instance Level permission:
if (currentUser.isPermitted ("winnebago:drive:eagle5")) {
System.out.println ("你拥有权限:winnebago:drive:eagle5");
} else {
System.out.println ("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
}
//注销,销毁session
currentUser.logout ( );
System.out.println("用户注销了...");
try {
String value2 = (String) session.getAttribute ("someKey");
System.out.println ("somekey的session值:"+value2);
}catch (UnknownSessionException e){
System.out.println("session在你注销后就已经销毁了!!");
}
//退出
System.exit (0);
}
}
总结:1.ini配置了用户 角色和权限 可以模拟数据库
2.加载数据到 SecurityManager 安全管理器
3.SecurityUtils设置SecurityManager
4.通过SecurityUtils获取subject
5.检查是否验证登陆,没有就把用户数据封装 UsernamePasswordToken token
6.login(token)登陆,交给realm验证账户密码等