Shiro身份验证大概分以下的六步:
第一步,先获取SecurityManager工厂,初始化SecurityManager;
第二步,实例化SecurityManager,并将SecurityManager绑定给SecurityUtils(全局设置,只设置一次)
第三步,向前端获取token(这是用户输入的,里面通常封装着username和password,也可以是其他可用于区分权限的数据)
第四步,创建Subject,里面包含了安全数据源
第五步,用Subject.login(token)方法验证登录信息进行身份验证,在这时用try-cat捕获异常即可,如果没有异常则身份验证通过,若有报错,可根据报错类型分析报错原因
第六步,如果身份认证验证成功,返回一个AuthenticationInfo实现。
如果想要测试的话建项目的大致结构:
测试用例:
1 package com.stw.shiro; 2 3 import junit.framework.Assert; 4 import org.apache.shiro.SecurityUtils; 5 import org.apache.shiro.authc.AuthenticationException; 6 import org.apache.shiro.authc.UsernamePasswordToken; 7 import org.apache.shiro.config.IniSecurityManagerFactory; 8 import org.apache.shiro.mgt.SecurityManager; 9 import org.apache.shiro.subject.Subject; 10 import org.apache.shiro.util.Factory; 11 import org.apache.shiro.util.ThreadContext; 12 import org.junit.After; 13 import org.junit.Test; 14 15 public class LoginLogoutTest { 16 @Test 17 public void testHelloworld() { 18 //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager 19 Factory<SecurityManager> factory = 20 new IniSecurityManagerFactory("classpath:shiro.ini"); 21 22 //2、得到SecurityManager实例 并绑定给SecurityUtils 23 org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); 24 SecurityUtils.setSecurityManager(securityManager); 25 26 //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) 27 Subject subject = SecurityUtils.getSubject(); 28 UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123"); 29 30 try { 31 //4、登录,即身份验证 32 subject.login(token); 33 System.out.println("验证通过!"); 34 } catch (AuthenticationException e) { 35 System.out.println("用户名或密码错误!"); 36 //5、身份验证失败 37 } 38 39 Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录 40 41 //6、退出 42 subject.logout(); 43 } 44 45 @Test 46 public void testCustomRealm() { 47 //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager 48 Factory<org.apache.shiro.mgt.SecurityManager> factory = 49 new IniSecurityManagerFactory("classpath:shiro-realm.ini"); 50 51 //2、得到SecurityManager实例 并绑定给SecurityUtils 52 org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); 53 SecurityUtils.setSecurityManager(securityManager); 54 55 //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) 56 Subject subject = SecurityUtils.getSubject(); 57 UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123"); 58 59 try { 60 //4、登录,即身份验证 61 subject.login(token); 62 } catch (AuthenticationException e) { 63 //5、身份验证失败 64 e.printStackTrace(); 65 } 66 67 Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录 68 69 //6、退出 70 subject.logout(); 71 } 72 73 @Test 74 public void testCustomMultiRealm() { 75 //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager 76 Factory<org.apache.shiro.mgt.SecurityManager> factory = 77 new IniSecurityManagerFactory("classpath:shiro-multi-realm.ini"); 78 79 //2、得到SecurityManager实例 并绑定给SecurityUtils 80 org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); 81 SecurityUtils.setSecurityManager(securityManager); 82 83 //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) 84 Subject subject = SecurityUtils.getSubject(); 85 UsernamePasswordToken token = new UsernamePasswordToken("wang", "123"); 86 87 try { 88 //4、登录,即身份验证 89 subject.login(token); 90 System.out.println("身份验证成功"); 91 } catch (AuthenticationException e) { 92 System.out.println("身份登录失败"); 93 e.printStackTrace(); 94 System.out.println(e); 95 } 96 97 Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录 98 99 //6、退出 100 subject.logout(); 101 } 102 @Test 103 public void testJDBCRealm() { 104 //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager 105 Factory<org.apache.shiro.mgt.SecurityManager> factory = 106 new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini"); 107 108 //2、得到SecurityManager实例 并绑定给SecurityUtils 109 org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance(); 110 SecurityUtils.setSecurityManager(securityManager); 111 112 //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证) 113 Subject subject = SecurityUtils.getSubject(); 114 UsernamePasswordToken token = new UsernamePasswordToken("zhang", "1234"); 115 116 try { 117 //4、登录,即身份验证 118 subject.login(token); 119 System.out.println("身份验证成功"); 120 } catch (AuthenticationException e) { 121 //5、身份验证失败 122 e.printStackTrace(); 123 System.out.println("身份登录失败"); 124 } 125 126 Assert.assertEquals(true, subject.isAuthenticated()); //断言用户已经登录 127 128 //6、退出 129 subject.logout(); 130 } 131 132 133 @After 134 public void tearDown() throws Exception { 135 ThreadContext.unbindSubject();//退出时请解除绑定Subject到线程 否则对下次测试造成影响 136 } 137 }
可信数据源:
package com.stw.realm; import org.apache.shiro.authc.*; import org.apache.shiro.realm.Realm; public class MyRealm1 implements Realm { public String getName() { return "myrealm1"; } public boolean supports(AuthenticationToken token) { //仅支持UsernamePasswordToken类型的Token return token instanceof UsernamePasswordToken; } 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()); } }
如要链接数据库,需配置:
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm dataSource=com.alibaba.druid.pool.DruidDataSource dataSource.driverClassName=com.mysql.jdbc.Driver dataSource.url=jdbc:mysql://localhost:3306/shiro dataSource.username=root dataSource.password=123456 jdbcRealm.dataSource=$dataSource securityManager.realms=$jdbcRealm
详细请看开涛老师的教程。