本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
每年都有很多新框架诞生,而每年又有需要框架被淘汰!框架能够帮助我们缩短开发周期,架构设计的难度,让我们更多的去关注业务,而不是架构的实现。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进行下载!
版权声明:本文为博主原创文章,未经博主允许不得转载。
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!