shiro 实现用户登陆认证授权
认证流程
1. 首先调用Subject.login(token)进行登录,其会自动委托给Security Manager,调用之前必须通过
SecurityUtils. setSecurityManager()设置;
2. SecurityManager负责真正的身份验证逻辑;它会委托给Authenticator进行身份验证;
3. Authenticator才是真正的身份验证者,Shiro API中核心的身份认证入口点,此处可以自定义插入自己的实
现;
4. Authenticator可能会委托给相应的AuthenticationStrategy进行多Realm身份验证,默认
ModularRealmAuthenticator会调用AuthenticationStrategy进行多Realm身份验证;
5. Authenticator会把相应的token传入Realm,从Realm获取身份验证信息,如果没有返回/抛出异常表示身份
验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。
授权流程
1. 首先调用Subject.isPermitted/hasRole接口,其会委托给SecurityManager,而SecurityManager接着会委托
给Authorizer;
2. Authorizer是真正的授权者,如果我们调用如isPermitted(“user:view”),其首先会通过PermissionResolver
把字符串转换成相应的Permission实例;
3. 在进行授权之前,其会调用相应的Realm获取Subject相应的角色/权限用于匹配传入的角色/权限;
4. Authorizer会判断Realm的角色/权限是否和传入的匹配,如果有多个Realm,会委托给
ModularRealmAuthorizer进行循环判断,如果匹配如isPermitted/hasRole会返回true,否则返回false表示
授权失败。
1.自定义realms 类
必须继承 AuthorizingRealm 抽象类
package com.zhao; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import java.util.ArrayList; import java.util.List; /** * 自定义realms 对象 * 继承 AuthorizingRealm */ public class RealmDemo extends AuthorizingRealm { /** * 设置 RealmDemo 名字 ,自定义realms 对象 过多时避免重复 * @param name */ @Override public void setName(String name) { super.setName("realmDemo"); } /** * 授权 * 获取到用户的授权数据(用户的权限数据) * 根据认证的用户 获取到他的权限信息 * @param principals 包含了所有的已认证的安全数据 * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println(" 授权 AuthorizationInfo "); //1.获取安全数据 username ,有可能是用户id String primaryPrincipal = (String)principals.getPrimaryPrincipal(); //2.根据 username 或者id查询用户 //3.查询用户的角色 和权限信息 //权限 List<String> perms =new ArrayList<>(); perms.add("user:save"); perms.add("user:find"); //角色 List<String> roles =new ArrayList<>(); roles.add("ordinary"); roles.add("admin"); //4.构造返回 SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); //设置权限集合 info.addStringPermissions(perms); //设置角色集合 info.addRoles(roles); return info; } /** * 认证 * 根据用户名密码进行登录,登录之后将用户数据进行保存 * 认证的目的,比较用户名和密码是否与数据库中的一致 * 将安全数据存入到shiro进行保管 * @param authenticationToken 登录构造的 UsernamePasswordToken * @return AuthenticationInfo 授权数据 * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println(" 认证 AuthenticationInfo "); //1. 构造 UsernamePasswordToken UsernamePasswordToken uptoken=(UsernamePasswordToken)authenticationToken; //2.获取输入的用户名密码 String username = uptoken.getUsername(); String password = new String(uptoken.getPassword()); //3.根据用户名查询数据 //4.比较密码和数据库中的密码是否一致(密码可能需要加密) if(username.equals("张三")&&password.equals("123456")){ //5.成功 向 shiro存入数据 /** * *@param principal与指定领域关联的“primary”主体。 安全数据 * *@param credentials验证给定主体的凭据。 密码 * *@param realmName从中获取主体和凭据的域。 当前realm 名称 getName() 获取到的是当前realm的名称 ,他的父类方法 */ SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,password,getName()); return simpleAuthenticationInfo; }else { //6.失败 返回null 或者抛出 自定义的异常 return null; } } }
2.配置文件
[main] permRealm=com.zhao.RealmDemo #注册realm到securityManager securityManager.realms=$permRealm
3.测试
package com.zhao.shiro.test; import org.apache.shiro.SecurityUtils; 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.Before; import org.junit.Test; public class ShiroTest3 { @Before public void init(){ // 1.根据配置文件shiroDemo.ini 文件 创建 SecurityManagerFactor Factory<SecurityManager> factory= new IniSecurityManagerFactory("classpath:shiroDemoRealm.ini"); //2.通过工厂获取SecurityManager SecurityManager securityManager = factory.getInstance(); //* 3.将SecurityManager绑定到当前运行环境 SecurityUtils.setSecurityManager(securityManager); } /** * 测试用户登录 * 用户认证 * 1.根据配置文件shiroDemo.ini 文件 创建 SecurityManagerFactor * 2.通过工厂获取SecurityManager * 3.将SecurityManager绑定到当前运行环境 * 4.从当前环境中构造subject * 5.构造shiro登陆的数据 * 6.主题登录 */ @Test public void login1(){ //* 4.从当前环境中构造subject Subject subject = SecurityUtils.getSubject(); // * 5.构造用户认证的数据 // String userName="lisi"; // String password = "10086"; String userName="张三"; String password = "123456"; UsernamePasswordToken token =new UsernamePasswordToken(userName,password); // * 6.主题登录 //执行 login1--》realm 域中的认证方法 subject.login(token); //登录之后完成授权 ,是否具有某个角色 System.out.println(subject.hasRole("admin")); //是否有admin 这个角色 System.out.println(subject.hasRole("root")); //是否有root 这个角色 System.out.println(subject.isPermitted("user:save"));// 是否有 user:save 这个权限 } }
参考视频 :https://www.bilibili.com/video/av75572951?p=108

浙公网安备 33010602011771号