$Shiro前端
Apache-shiro 是一种简便的java安全框架,对于身份认证,受权 。权限管理有着很简单的使用方法java
subject :访问当前系统的用户 主体能够是用户也能够是程序 。算法
Shrio SecurityManager :安全管理器 ,shiro 的核心。相似于SpringMVC的前端控制器(DispatcherServlet),接收来自 “subject” 的委托,与认证器 ,受权器等进行交互数据库
Realm:至关于dataSource 安全的数据源 充当了shiro 与 数据源 的 “链接器” 当执行认证,受权时,shiro会从realm中比对信息是否合法合理。apache
Shiro认证(使用ini方式进行测试)---> 全部项目均使用maven方式编写 安全
shiro.ini(建立一个配置文件存放信息 。模拟从数据库中获取信息)框架
[users] #帐号=密码 chen=123 root=10001
新建一个测试类maven
加载配置文件 获取当前用户信息性能
经过单独测试编写两个异常信息 ,反馈当用户名出错 或者密码出错的状况,测试
package com.shiro.test; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.junit.Test; /** * 测试shiro * * @author 18609 * */ public class ShiroTest { @Test public void logintest() { // 建立工厂,加载资源 shiro工厂 调用Factory接口 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini"); // 经过工厂对象建立SecurityManager对象 SecurityManager manager = factory.getInstance(); // 将SecurityManager绑定当前环境中。让系统随时访问SecurityManager对象 SecurityUtils.setSecurityManager(manager); // 建立当前登录主体 未认证 Subject subject = SecurityUtils.getSubject(); // 收集当前用户信息 UsernamePasswordToken token = new UsernamePasswordToken("root", "10001"); try { subject.login(token); System.out.println("登陆成功"); } catch (IncorrectCredentialsException e) { // 密码异常错误 System.out.println("登录失败,密码错误!"); } catch (UnknownAccountException e) { // 帐号异常错误 System.out.println("登录失败,帐号不存在!"); } finally { subject.logout(); System.out.println("注销成功"); } } }
经过token 获取到username 并传给Realm验证 ,若是存在相同数据,封装成以下AuthenticationInfo对象进行返回 不然为null
自定义一个Realm类 继承 AuthenticatingRealm 并复写其类的getName() 实现两个方法 进行认证操做
package com.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.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthenticatingRealm; import org.apache.shiro.subject.PrincipalCollection; public class MyRealm extends AuthenticatingRealm { // 重写 注意返回值 public String getName() { return "MyRealm"; } // 受权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } // 认证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println(token); // 获取用户名 String username = (String) token.getPrincipal(); // 经过用户名查询 并返回 if (!"root".equals(username)) { return null; } String password = "10001"; // 对比当前信息 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName()); return info; } }
shiro-realm.ini
#自定义realm MyRealm=com.shiro.Realm.MyRealm #指定自定义realm的实现 securityManager.realms=$MyRealm
执行流程
认证成功
Shiro加密认证(使用ini方式进行测试)---> 全部项目均使用maven方式编写
shiro 对md5加密有着较好的支持,这里不说明为何要进行加密措施。
测试几种加密方法 越往下 加密措施越好。越不易破解(如下加密方式全选用第三种 密码 + salt + 散列次数)
package com.shiro.test; import org.apache.shiro.crypto.hash.Md5Hash; import org.junit.Test; public class Md5Test { @Test public void test() { String password = "10001"; // 密码加密 Md5Hash hash = new Md5Hash(password); System.out.println("password: " + hash); // 密码 + salt(用户名) Md5Hash hash1 = new Md5Hash(password, "root"); System.out.println("passsword + salt :" + hash1); // 密码 + salt(用户名) + 散列次数 安全性能更好 Md5Hash hash2 = new Md5Hash(password, "root", 3); System.out.println("passsword + salt + count :" + hash2); } }
测试类
package com.shiro.test; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.junit.Test; /** * 测试shiro * * @author 18609 * */ public class ShiroTest { @Test public void loginByPasswordtest() { // 建立工厂,加载资源 shiro工厂 调用Factory接口 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-md5.ini"); // 经过工厂对象建立SecurityManager对象 SecurityManager manager = factory.getInstance(); // 将SecurityManager绑定当前环境中。让系统随时访问SecurityManager对象 SecurityUtils.setSecurityManager(manager); // 建立当前登录主体 未认证 Subject subject = SecurityUtils.getSubject(); // 收集当前用户信息 UsernamePasswordToken token = new UsernamePasswordToken("root", "10001"); try { subject.login(token); System.out.println("登陆成功"); } catch (IncorrectCredentialsException e) { // 密码异常错误 System.out.println("登录失败,密码错误!"); } catch (UnknownAccountException e) { // 帐号异常错误 System.out.println("登录失败,帐号不存在!"); } finally { subject.logout(); System.out.println("注销成功"); } } }
新建passwordRealm类 进行加密认证
package com.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.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; public class PasswordRealm extends AuthorizingRealm {
//注意返回值 public String getName() { return "PasswordRealm"; } // 受权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } // 认证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println(token); // 获取用户名 String username = (String) token.getPrincipal(); // 经过用户名查询 并返回 if (!"root".equals(username)) { return null; } // passsword + salt + count :2634402341f810a1007d7c4b4521aef5 String password = "2634402341f810a1007d7c4b4521aef5"; // 对比当前信息 1.用户名 2.密码 3.salt(加盐加密ByteSource.Util.bytes("root")) 4.重写当前的realm名字 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo (username, password, ByteSource.Util.bytes("root"),getName()); return info; } }
ByteSource.Util.bytes("root") :进行盐(salt)加密认证 内填用户名
不写此参数使用salt加密 会报错。报密码错误的问题 由于没有进行用户名认证。
shiro-md5.ini
填写与测试中相关的信息 红色标注不能更改必填项 蓝色标注更改项。
#定义凭证匹配器 credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher #散列算法 credentialsMatcher.hashAlgorithmName=md5 #散列次数 credentialsMatcher.hashIterations=3 #指定passwordRealm的realm myRealm=com.shiro.Realm.PasswordRealm #引用凭证 myRealm.credentialsMatcher=$credentialsMatcher #引用指定realm securityManager.realms=$myRealm
经过设置加密的密码 存入数据库中 ,并进行加密认证 数据相同时,经过认证。登陆成功。