Shiro基础
-
权限管理
1.1 什么是权限管理?
-
起步
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-aspectj</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.5.3</version> </dependency>
-
第一个程序
-
配置文件
[users] zhangsan=123 lisi=456 wangwu=789
-
java程序
package com.study; 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.mgt.DefaultSecurityManager; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.subject.Subject; /** * ClassName:TestAuthenticator * Package:com.study * Description: study shiro * * @Date:2021/1/15 20:39 * @com.chuangmei */ public class TestAuthenticator { public static void main(String[] args) { //1.创建安全管理器对象 SecurityManager securityManager = new DefaultSecurityManager(); //2.给安全管理器设置realm ((DefaultSecurityManager) securityManager).setRealm(new IniRealm("classpath:shiro.ini")); //3.SecurityUtils 给全局安全工具类设置安全管理器 SecurityUtils.setSecurityManager(securityManager); //4.关键对象 subject主体 Subject subject = SecurityUtils.getSubject(); //5.创建令牌 UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("lisi","4156"); try{ //获取认证状态 未认证返回false 已认证返回true System.out.println(subject.isAuthenticated()); //认证,如果认证成功不会发生异常 subject.login(usernamePasswordToken); //获取认证状态当前为true System.out.println(subject.isAuthenticated()); }catch(UnknownAccountException unknowAccountException){ //用户名错误发生UnknownAccountException异常 unknowAccountException.printStackTrace(); System.out.println("账户名不存在!"); }catch (IncorrectCredentialsException incorrectCredentialsException){ //密码错误 发生IncorrectCredentialsException异常 incorrectCredentialsException.printStackTrace(); System.out.println("密码错误!"); } } }
-
-
认证
4.1 最终用户名的比较是在SimpleAccountRealm中的doGetAuthenticationInfo方法中进行用户名的校验
4.2 密码的校验是在AuthenticatingRealm中的assertCredentialsMatch方法中完成的
4.3
AuthenticatingRealm 认证realm doGetAuthenticationInfo(自定义realm重写此方法)
AuthenorizingRealm 授权realm doGetAuthorizationInfo
Shiro实践
-
SimpleAccountRealm
//认证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken)token; SimpleAccount account = this.getUser(upToken.getUsername()); if (account != null) { if (account.isLocked()) { throw new LockedAccountException("Account [" + account + "] is locked."); } if (account.isCredentialsExpired()) { String msg = "The credentials for account [" + account + "] are expired"; throw new ExpiredCredentialsException(msg); } } return account; } //授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String username = this.getUsername(principals); this.USERS_LOCK.readLock().lock(); AuthorizationInfo var3; try { var3 = (AuthorizationInfo)this.users.get(username); } finally { this.USERS_LOCK.readLock().unlock(); } return var3; }
-
main (测试)
package com.study; import com.study.Realm.CustomerRealm; 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.mgt.DefaultSecurityManager; import org.apache.shiro.subject.Subject; /** * ClassName:CustomerRealmAuthenticator * Package:com.study * Description: * * @Date:2021/1/16 20:40 * @com.chuangmei */ public class CustomerRealmAuthenticator { public static void main(String[] args) { //创建安全管理器 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); //设置自定义realm defaultSecurityManager.setRealm(new CustomerRealm()); //将安全管理器添加至工具类 SecurityUtils.setSecurityManager(defaultSecurityManager); //通过安全工具类获取subject Subject subject = SecurityUtils.getSubject(); //创建token UsernamePasswordToken token = new UsernamePasswordToken("renyi", "123"); try{ System.out.println(subject.isAuthenticated()); subject.login(token); System.out.println(subject.isAuthenticated()); if (subject.isAuthenticated()){ System.out.println("登录成功"); } }catch (UnknownAccountException unknownAccountException){ unknownAccountException.printStackTrace(); System.out.println("用户名错误!"); }catch(IncorrectCredentialsException incorrectCredentialsException){ incorrectCredentialsException.printStackTrace(); System.out.println("密码错误!"); } } }
-
CustomerRealm
自定义Realm 需覆盖AuthorizingRealm
中的认证和授权方法package com.study.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; /** * ClassName:CustomerRealm * Package:com.study * Description: * * @Date:2021/1/16 20:37 * @com.chuangmei */ public class CustomerRealm extends AuthorizingRealm { //授权 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } //认证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //从token中获取username String principal = (String) authenticationToken.getPrincipal(); //renyi应该是数据库中查询到的真实数据 if ("renyi".equals(principal)){ /** * 创建SimpleAuthenticationInfo对象 * 参数1: 代表数据库中的用户名 * 参数2: 代表数据库中的密码 * 参数3: 表示realm名,可以用getname()方法获取 */ SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo("renyi","123",this.getName()); return simpleAuthenticationInfo; } return null; } }
-
MD5和salt
-
MD5
-
shiroMD5加密
public class TestShiroMD5 { public static void main(String[] args) { /** * 使用 md5 */ Md5Hash md5Hash = new Md5Hash("123"); //获取加密后的数据 System.out.println(md5Hash.toHex()); /** * MD5 + salt */ Md5Hash md5Hash1 = new Md5Hash("123","X0*7ps"); System.out.println(md5Hash1.toHex()); /** *推荐 MD5 + salt + hash散列 */ Md5Hash md5Hash2 = new Md5Hash("123","X0*7PS",1024); System.out.println(md5Hash2.toHex()); } }
-
-
shiroMD5认证
-
当我们使用MD5加密后普通的认证无法通过,所以我们需要给认证也加上MD5
-
自定义Realm
package com.study.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; /** * ClassName:CustomerMD5Realm * Package:com.study.Realm * Description:当我们使用MD5加密后普通的认证无法通过,所以我们需要给认证也加上MD5 * MD5 + salt + hash散列 * * @Date:2021/1/17 20:44 * @com.chuangmei */ public class CustomerMD5Realm extends AuthorizingRealm { protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { return null; } protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //principal String principal = authenticationToken.getPrincipal().toString(); //比较用户名 if ("renyi".equals(principal)){ /** * 此处的renyi和123都是来自数据库的,如果我的密码123经过了md5加密怎么办? * 假设此处的123经过了md5 + 随机盐 + hash散列 明文 123 密文 d5a6b89a330bc2d7956092d2652890e0 * 我们需要修改shiro在进行密码比较时候的默认策略 */ return new SimpleAuthenticationInfo( "renyi", "d5a6b89a330bc2d7956092d2652890e0", ByteSource.Util.bytes("X0*7ps"), this.getName()); } return null; } }
-
测试
package com.study; import com.study.Realm.CustomerMD5Realm; 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.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.subject.Subject; /** * ClassName:CustomerMD5RealmAuthenticator * Package:com.study * Description: * * @Date:2021/1/17 20:51 * @com.chuangmei */ public class CustomerMD5RealmAuthenticator { public static void main(String[] args) { //创建安全管理器 DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager(); //设置realm的hash凭证匹配器 CustomerMD5Realm realm = new CustomerMD5Realm(); HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); //指定MD5算法 credentialsMatcher.setHashAlgorithmName("md5"); //指定散列次数 credentialsMatcher.setHashIterations(1024); //设置凭证匹配器 realm.setCredentialsMatcher(credentialsMatcher); //注入realm defaultSecurityManager.setRealm(realm); //将安全管理器设置到Securityutils SecurityUtils.setSecurityManager(defaultSecurityManager); //获取主体 Subject subject = SecurityUtils.getSubject(); //token UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("renyi", "123"); //认证 try { System.out.println(subject.isAuthenticated()); subject.login(usernamePasswordToken); System.out.println(subject.isAuthenticated()); System.out.println("登录成功!"); } catch (UnknownAccountException unKnowAccountException) { unKnowAccountException.printStackTrace(); System.out.println("用户名错误!"); } catch (IncorrectCredentialsException incorrectCredentialsException){ incorrectCredentialsException.printStackTrace(); System.out.println("密码错误!"); } } }
-