背景:
1、jdbcRealm 已经实现了成数据库中获取用户的验证信息,但是jdbcRealm 灵活性太差。如果要实现自己的一些特殊应用时将不能支持。这个时候
可以通过自定义Realm来实现身份认证的功能。
2、Realm是一个接口,在接口中定义了根据token获得认证信息的方法,shiro内容实现了一系列的realm。这些不同Realm实现类提供了不同的共功能.
AuthenticationgRealm实现了获取身份信息的功能,AuthorizingRealm 实现了获取权限信息的功能。通常自定义Realm需要继承AurhorizingRealm
,即这样可以提供身份认证的自定义方法也可以实现授权的自定义方法。
自定义damo:
1、新建一个Java项目
2、导包
3、项目结构
4、编写自定义Realm
package com.text.shiro;
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;
/*
* 自定义Realm实现,该Realm类提供了两个方法
* doGetAuthorizationInfo 获取认证信息
* doGetAuthenticationInfo 获取权限信息
*/
public class UserRealm extends AuthorizingRealm {
@Override
public String getName() {
return "userRealm";
}
//完成身份认证(从数据库中去数据)并且放回认证信息
//如果身份认证失败,返回null
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
String principal = (String)token.getPrincipal();
System.out.print("username=======" +principal);
//这里要根据principal 到数据库中查询password
//假定查询到是password为 1111
String pwd = "1111";
SimpleAuthenticationInfo Info = new SimpleAuthenticationInfo(principal, pwd, getName());
return Info;
}
//获取授权信息
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
// TODO Auto-generated method stub
return null;
}
}
5、编写测试类
package com.txt.shiro;
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.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
public class AuthenticationDemo {
public static void main(String[] args) {
//1创建SecurityManager工厂,加载配置文件
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2 通过SecurityManager工厂获取SecurityManager实例
SecurityManager securityManager = factory.getInstance();
//3将SecurityManager设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//通过SecurityUtils获取subject
Subject subject = SecurityUtils.getSubject();
System.out.print(subject+"\n");
//这里是登录时用户填写的用户名和密码
//shiro里存放的是系统中用户的信息,也可以存放到数据库中
UsernamePasswordToken token = new UsernamePasswordToken("zhansan","1s111");
//进行登录认证
try {
subject.login(token);
//subject.isAuthenticated()判断是否登录成功,若是不成功会报错
if(subject.isAuthenticated()) {
System.out.print("登录成功\n");
}
} catch (UnknownAccountException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.print("用户或者密码不正确1\n");
} catch (IncorrectCredentialsException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.print("用户或者密码不正确\n");
}
}
}
6、编写ini、log4j.properties
ini
[main]
userRealm=com.text.shiro.UserRealm
securityManager.realm=$userRealm
log4j
log4j.rootCategory=INFO, CONSOLE ,LOGFILE
log4j.logger.com.bjsxt.mapper=DEBUG
log4j.logger.com.text.shiro=INFO
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%C %d{YYYY-MM-dd hh:mm:ss} %m %n
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=E:/my.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%m %n
测试结果: