Shiro身份认证流程如下:请看Shiro架构图
登录的时候-------->给Security Manager进行管理----------------->Authenticator----------------------->Authentication Strategy---------------------->各种Realm
什么叫做Realm?
Realm:域,Shiro从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。
一个例如如下:
单Realm
shiro-realm.ini 文件内容如下:
[main] #声明一个realm myRealm=com.lgy.shiro.MyRealm #指定securityManager的realms实现 securityManager.realms=$myRealm
自定义Realm实现如下:
package com.lgy.shiro; 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; public class MyRealm implements Realm { public String getName() { return "myrealm1"; } public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; //仅支持UsernamePasswordToken类型的Token } public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String)token.getPrincipal(); //得到用户名 String password = new String((char[])token.getCredentials()); //得到密码 if(!"zhang".equals(username)) { throw new UnknownAccountException(); //如果用户名错误 } if(!"123".equals(password)) { throw new IncorrectCredentialsException(); //如果密码错误 } //如果身份认证验证成功,返回一个AuthenticationInfo实现; return new SimpleAuthenticationInfo(username, password, getName()); } }
以上3个方法是继承Realm的接口:
String getName(); //返回一个唯一的Realm名字 boolean supports(AuthenticationToken token); //判断此Realm是否支持此Token AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException; //根据Token获取认证信息
测试类如下:
@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("zhang", "123"); try { // 4、登录,即身份验证 subject.login(token); } catch (AuthenticationException e) { // 5、身份验证失败 e.printStackTrace(); } Assert.assertEquals(true, subject.isAuthenticated()); // 断言用户已经登录 // 6、退出 subject.logout(); }