此案例是用IDEA创建maven的java项目
步骤一:在java文件夹下创建自定义的Realm类,注意自定义的Realm要继承该类要继承AuthorizingRealm,我们其实只是重写其中的授权和认证方法。然后通过下面我们定义的ini文件来告诉shiro框架来调用我们的自定义的这个Realm类。
此案例中我将该类命名为:PerRealm
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.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import java.util.ArrayList;
import java.util.List;
//自定义Realm
public class PerRealm extends AuthorizingRealm {
//授权(iz)。我们在这里面将用户的真实权限添加进SimpleAuthorizationInfo对象中,当执行类在调用isPermitted()和hasRoles()时就会判断前台用户是否是此授权方法中添加的的角色,以及是否有此方法中添加的权限
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//判断认证通过的用户即已经通过下面方法认证的用户在执行此方法的用户是否包含某些角色和权限
//角色
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//该用户对应多个角色用List装起来,作为addRoles的参数,模拟数据库中的该用户的角色列表,表示该用户有多个角色。这里的角色代表的是以后数据库中的真实角色。执行类中,也就是调用hasRoles的那个类只是判断是否是我们在此处添加的角色
List roles=new ArrayList();
roles.add("role1");
roles.add("role2");
info.addRoles(roles);//注意:无论是权限还是角色都是用的一个SimpleAuthorizationInfo对象
//该用户有多个权限也用list装起来,作为addStringPermission()的参数,模拟数据库中的该用户的权限列表,表示该用户有多个权限。这里的权限代表的是以后数据库中的真实权限。行类中,也就是调用isPermitted()的那个类只是判断是否是我们在此处添加的权限
List pers=new ArrayList();
pers.add("user:create");
pers.add("users:update");
info.addStringPermissions(pers);//注意:无论是权限还是角色都是用的一个SimpleAuthorizationInfo对象
return info;//注意授权最后返回的为SimpleAuthorizationInfo对象,因为所有正确的信息都包含在了SimpleAuthorizationInfo对像中,前后台信息的比对由底层完成。
}
//认证(ic),即判断前台也就是执行类中login传过来的subject主体中的用户名和密码和数据库中存的真实的用户名和密码是否一致。一致的话就执行上面的授权方法
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username=(String)authenticationToken.getPrincipal();//获取身份信息,即前台(调用login方法的类)传来的用户名
if("admin".equals(username)){//admin代表数据库中的用户名即真实用户名后期该位置会被数据库查询的信息代替,username代表前台传过来的用户名
return new SimpleAuthenticationInfo(username,authenticationToken.getCredentials(),"realm1");//这几个参数分别代表前台传来的用户名,密码和realname。此处因为不想验证密码,所以直接写authenticationToken.getCredentials(),无论前台写什么密码都对。realname可以自定义,随便写。
}
return null;//注意认证通过认证后返回的是SimpleAuthenticationInfo对象,认证失败时是null
}
}
步骤二:在Resources下创建ini文件,告诉shiro框架调用我们自定义的Realm类
此案例我将该ini文件命名为:shiro-perdb.ini
#将凭证匹配器设置到realm,左侧myRealm是自定义的名称,右侧com.qf.PerRealm,是自定义的Realm的路径(即包名加文件名)
myRealm=com.qf.PerRealm
#左侧securityManager.realms固定搭配,右侧$myRealm即$加上上面的名字
securityManager.realms=$myRealm
#号为注释内容
步骤三:在java文件夹下创建执行类测试我们的自定义的Realm即PerRealm
此案例我将测试类命名为:TestDemo1
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 java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class TestDemo1 {
public static void main(String[] args) {
//创建安全管理对象
Factory<SecurityManager> factory=
new IniSecurityManagerFactory("classpath:shiro-perdb.ini");//注意着个泛型导的包,由于自动导的是java.lang包,所以手动导的。classpath:这是固定的,不能少了。
//创建具体对象
SecurityManager instance=(SecurityManager) factory.getInstance();
//添加安全管理器对象导工具类中
SecurityUtils.setSecurityManager(instance);
//创建主体信息
Subject subject=SecurityUtils.getSubject();
//创建UsernamePasswordToken 对象保存用户登录时的用户名和密码。--------------灵活步骤
UsernamePasswordToken token=
new UsernamePasswordToken("admin","123");//用户登录后我们将其存在UsernamePasswordToken中,用于subject.isAuthenticated()判断存的这个是否和shiro.ini文件中的一致。
//认证
subject.login(token); //提交认证,并将用户名和密码存在subject中。利用login方法将用户写的用户名和密码提交到Realm的认证部分进行认证,下面的isAuthenticated()方法则是认证后返回的结果,该返回结果只有true和false
//测试认证结果(subject.isAuthenticated()用于判断主体信息即用户名和密码是否正确)
/*此行代码是比对效果*/ boolean b = subject.isAuthenticated();//isAuthenticated用于比对UsernamePasswordToken 中存的是否存在于shiro-per.ini中,若在则返回true。不存在shiro-per.ini中则返回false
System.out.println("认证结果一:"+b);
//判断授权
//只有一个角色或权限时
//本次例子中的重点代码,就这两行
boolean permitted = subject.isPermitted("user:create");//isPermitted()是判断权限的,即[roles]下的value。本段代码意思是判断zhangsan这个用户对应的角色中是否有user:create这个权限。有一个角色有即可返回true
System.out.println("permitted:"+permitted);
boolean role1 = subject.hasRole("role1");//hasRole()是判断角色的,即[users]的value。本段代码意思是判断zhangsan是否是role1这个角色
System.out.println("role1:"+role1);
//当有多个角色或权限时
boolean[] permitted1 = subject.isPermitted("user:create", "user:select");//zhanssan是否有这当中的权限?
System.out.println("permitted1:"+Arrays.toString(permitted1));
List list=new ArrayList();
list.add("role1");
list.add("role3");
boolean[] booleans = subject.hasRoles(list);//判断是否是集合中这些角色
System.out.println("bolleans:"+ Arrays.toString(booleans));
//退出
subject.logout();
boolean b2=subject.isAuthenticated();
System.out.println("认证结果2:"+b2);
}
}
此案例我的框架结构图:
此案例运行结果图: