shiro默认使用自带的IniRealm,IniRealm从ini配置文件中读取用户的信息。大部分情况下我们是需要从数据库中读取用户信 息,所以要自定义realm
[main]
myRealm=cn.wit.realm.MyRealm
#依赖注入
SecurityManager.realm=$myRealm
配置应用程序的SecurityManager实例及任何它的依赖组件(比如Realms)
[users]
可以像认证demo中配置静态用户(张三=123)。还可以定义角色(lisi=456,role1,role2)
将用户和用户和角色联系起来(这里就很rbac了!)
[users]
zhangsan=1111,role1
[roles]
role=user:add,user:delete
使用JdbcRealm进行认证
- 在指定的dataSource锁对应的数据库中应该有用户表users,该表中有username,password,password_salt等字段,这些名称都是jdbcRealm源码中SQL语句中的,所以,如果创建数据库时不按照源码的字段名来建表,就没法使用JdbcRealm
JdbcRealm demo
jar包
数据库设计
日志
log4j.rootLogger=Info, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
shiro.ini
[main]
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/login
dataSource.user=root
dataSource.password=wityy
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
securityManager.realm=$jdbcRealm
[users]
zhangsan=123
main中dataSource用c3p0数据库连接池 连接数据库,mysql专栏中有关于数据库连接池的内容。 ,配置完dataSource后,配置jdbcRealm,将dataSource给jdbcRealm,将jdbcRealm赋值给SecurityManager,赋值前加$
main
package cn.wit.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
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.realm.Realm;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
/**
* 完成用户认证功能
* @author Administrator
*
*/
public class Authentication {
public static void main(String[] args) {
//拿到SecurityManager并将它放到环境当中
Factory<SecurityManager>factory=new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//拿到subject接口
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken taken=new UsernamePasswordToken("zhangsan","123");
try {
subject.login(taken);
if(subject.isAuthenticated()){
System.out.println("登录成功");
}
} catch (UnknownAccountException e) {
System.out.println("账号或密码错误");
}catch (IncorrectCredentialsException e) {
System.out.println("账号或密码错误");
}
}
}
验证策略
在说具体内容之前先了解一下认证过程的源码
从login进入源码的过程参见该篇文章:认证过程
从进入认证器部分的源码开始
查看Authenticator认证器 接口的类层次,具体的实现类是ModularRealmAuthenticator
l里边有个authenticationStratery类属性,继续跳转
该接口的类层次,三个类分别代表三种不同的认证策略
加入AllSuccessfulStrategy后的ini文件
[main]
dataSource=com.mchange.v2.c3p0.DriverManagerDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/login
dataSource.user=root
dataSource.password=wityy
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
authenticationStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy
securityManager.realm=$jdbcRealm
securityManager.authenticator.authenticationStrategy=$authenticationStrategy
[users]
zhangsan=123