每年都有很多新框架诞生,而每年又有需要框架被淘汰!框架能够帮助我们缩短开发周期,架构设计的难度,让我们更多的去关注业务,而不是架构的实现。Shiro框架就是为我们省去了权限管理模块的相关设计和开发难度。
Shiro其实很简单,作为入门教程,这里我就从项目搭建开始讲起。
Shiro依赖的jar
commons-logging、shiro-core、druid、mysql-connector-java
构建maven的pom.xml文件如下:
<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>com.xttblog.shiro-demo1</groupId>
<artifactId>shiro-demo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.23</version>
</dependency>
</dependencies>
</project>
配置shiro.ini文件
内容如下:
[users]
shiro=123
xttblog=123
定义实体及关系

drop database if exists shiro;
create database shiro;
use shiro;
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `roles_permissions`;
CREATE TABLE `roles_permissions` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`role_name` varchar(100) DEFAULT NULL,
`permission` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_roles_permissions` (`role_name`,`permission`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
INSERT INTO `roles_permissions` VALUES ('1', 'role1', '+user1+10');
INSERT INTO `roles_permissions` VALUES ('3', 'role1', '+user2+10');
INSERT INTO `roles_permissions` VALUES ('2', 'role1', 'user1:*');
INSERT INTO `roles_permissions` VALUES ('4', 'role1', 'user2:*');
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
`password_salt` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_users_username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `users` VALUES ('2', 'shiro', '123', null);
DROP TABLE IF EXISTS `user_roles`;
CREATE TABLE `user_roles` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(100) DEFAULT NULL,
`role_name` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_roles` (`username`,`role_name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO `user_roles` VALUES ('1', 'shiro', 'role1');
INSERT INTO `user_roles` VALUES ('2', 'shiro', 'role2');
定义Realm
package com.xttblog.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.IncorrectCredentialsException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.realm.Realm;
/**
* Shiro框架学习demo
* :www.xttblog.com
* QQ1群:135430763(已满)
* QQ2群:454796847
* @author 涛哥
* @date 2016年8月8日14:46:10
*/
public class MyRealm implements Realm{
public String getName() {
return "myrealm";
}
public boolean supports(AuthenticationToken token) {
return token instanceof UsernamePasswordToken; //仅支持UsernamePasswordToken类型的Token
}
//Shiro的认证过程最终会交由Realm执行,这时会调用Realm的getAuthenticationInfo(token)方法
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
/**
* 1、检查提交的进行认证的令牌信息
* 2、根据令牌信息从数据源(通常为数据库)中获取用户信息
* 3、对用户信息进行匹配验证。
* 4、验证通过将返回一个封装了用户信息的AuthenticationInfo实例。
* 5、验证失败则抛出AuthenticationException异常信息。
*/
String username = (String)token.getPrincipal(); //得到用户名
String password = new String((char[])token.getCredentials()); //得到密码
if(!"shiro".equals(username)) {
throw new UnknownAccountException(); //如果用户名错误
}
if(!"123".equals(password)) {
throw new IncorrectCredentialsException(); //如果密码错误
}
//如果身份认证验证成功,返回一个AuthenticationInfo实现;
return new SimpleAuthenticationInfo(username, password, getName());
}
}
AuthenticationToken接口

AuthenticationToken用于收集用户提交的身份(如用户名)及凭据(如密码):
扩展接口RememberMeAuthenticationToken:提供了“boolean isRememberMe()”现“记住我”的功能;
扩展接口是HostAuthenticationToken:提供了“String getHost()”方法用于获取用户“主机”的功能。
Shiro提供了一个直接拿来用的UsernamePasswordToken,用于实现用户名/密码Token组,另外其实现了RememberMeAuthenticationToken和HostAuthenticationToken,可以实现记住我及主机验证的支持。
AuthenticationInfo接口

AuthenticationInfo的两个作用:
1、如果Realm是AuthenticatingRealm子类,则提供给AuthenticatingRealm内部使用的CredentialsMatcher进行凭据验证;(如果没有继承它需要在自己的Realm中自己实现验证)
2、提供给SecurityManager来创建Subject(提供身份信息)
Shiro测试用例
package com.xttblog.shiro.auth;
import junit.framework.Assert;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.util.ThreadContext;
import org.junit.After;
import org.junit.Test;
/**
* Shiro框架学习demo
* :www.xttblog.com
* QQ1群:135430763(已满)
* QQ2群:454796847
* @author 涛哥
* @date 2016年8月8日14:46:10
*/
public class LoginLogoutTest {
/**
* 通过数据源为:用户名/密码的键值对配置文件验证身份
*/
@Test
public void testHelloworld() {
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("shiro", "123");
try {
//4、登录,即身份验证
subject.login(token);
} catch (AuthenticationException e) {
//5、身份验证失败
System.out.println("身份验证失败:www.xttblog.com");
}
Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
//6、退出
subject.logout();
}
/**
* 通过数据源为:自定义Realm验证身份
*/
@Test
public void testCustomRealm() {
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("shiro", "123");
try {
//4、登录,即身份验证
subject.login(token);
} catch (AuthenticationException e) {
//5、身份验证失败
e.printStackTrace();
}
Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
//6、退出
subject.logout();
}
/**
* 通过数据源为:多个自定义Realm验证身份
*/
@Test
public void testCustomMultiRealm() {
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro-multi-realm.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("shiro", "123");
try {
//4、登录,即身份验证
subject.login(token);
} catch (AuthenticationException e) {
//5、身份验证失败
e.printStackTrace();
}
Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
//6、退出
subject.logout();
}
/**
* 通过数据源为:数据库的方式验证身份
*/
@Test
public void testJDBCRealm() {
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager> factory =
new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
//如果用户名不存在,则会报org.apache.shiro.authc.UnknownAccountException: No account found for user [xx用户名]异常
UsernamePasswordToken token = new UsernamePasswordToken("shiro", "123");
try {
//4、登录,即身份验证
subject.login(token);
} catch (AuthenticationException e) {
//5、身份验证失败
e.printStackTrace();
}
Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录
//6、退出
subject.logout();
}
@After
public void tearDown() throws Exception {
ThreadContext.unbindSubject();//退出时请解除绑定Subject到线程 否则对下次测试造成影响
}
}
其他的一些配置文件我就不贴了,我已共享到了群空间!或者到csdn进行下载!
版权声明:本文为博主原创文章,未经博主允许不得转载。

: » Shiro入门教程
原创文章,作者:3628473679,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/251462.html