一、Shiro读取ini文件
1.1 创建Maven项目:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.2</version>
</dependency>
</dependencies>
1.2 在resource目录下新建一个shiro.ini文件,内容如下:
[users]
zhangsan=123
lisi=123
admin=admin
1.3 创建一个testShiro1.java文件。
public class testShiro1{
@Test
public void testHelloShiro1(){
//1、获取SecurityManager工程,此处使用ini配置文件初始化SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro1.ini");
//2、得到SecurityManager实例,并绑定给SecurityUtils.
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123");
try {
//4、登录、即身份验证
subject.login(token);
System.out.println("登录成功!");
} catch (AuthenticationException e) {
System.out.println("登录失败");
//5、身份验证失败
e.printStackTrace();
}
//6、退出
subject.logout();
}
@Test
public void testHelloShiro2(){
//第二种方式创建securityManager (推荐)
DefaultSecurityManager securityManager = new DefaultSecurityManager();
IniRealm iniRealm = new IniRealm("classpath:shiro1.ini");
securityManager.setRealm(iniRealm);
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123");
try {
//4、登录、即身份验证
subject.login(token);
System.out.println("登录成功!");
} catch (AuthenticationException e) {
System.out.println("登录失败");
//5、身份验证失败
e.printStackTrace();
}
//6、退出
subject.logout();
}
}
以上例子,用户名和密码都是硬编码到ini文件中的,shiro会自动去ini文件中查找用户名和密码,然后和我们传入的用户名和密码进行匹配,通过login进行验证,成功则什么都不会发生,如果不正确则会抛出异常。
常见异常:
- AuthenticationException:认证异常的父类。
- UnknownAccountException:用户名错误。
- IncorrectCredentialsException:密码错误。
2.1 自定义MyRealm
创建一个MyRealm.java文件。
public class MyRealm implements Realm {
@Override
public String getName() {
return "myrealm1";
}
@Override
public boolean supports(AuthenticationToken token) {
//仅支持UsernamePasswordToken类型的Token
return token instanceof UsernamePasswordToken;
}
@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("MyRealm认证");
String username = (String) token.getPrincipal(); //得到用户名。
String password = new String((char[]) token.getCredentials());
if(!"zhangsan".equals(username)){
throw new UnknownAccountException(); //如果用户名错误
}
if(!"123456".equals(password)){
throw new IncorrectCredentialsException(); //如果密码错误
}
return new SimpleAuthenticationInfo(username,password,getName());
}
}
2.2 创建一个shiro2.ini文件。
#声明一个realm
myRealm1=com.zc.shiro.demo2.MyRealm
#指定securityManager的realms实现
securityManager.realms=$myRealm1
2.3 创建测试文件
public class LoginLogoutTest2 {
@Test
public void testHelloShiro(){
//1、获取SecurityManager工程,此处使用ini配置文件初始化SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro2.ini");
//2、得到SecurityManager实例,并绑定给SecurityUtils.
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");
try {
//4、登录、即身份验证
subject.login(token);
System.out.println("登录成功!");
} catch (AuthenticationException e) {
System.out.println("登录失败");
//5、身份验证失败
e.printStackTrace();
}
//6、退出
subject.logout();
}
}
上面代码中,自定义了一个Realm,再Realm中进行的密码的验证,这样比写死到ini文件中要更加的灵活,也更方便。
2.4 多Realm配置
ini文件配置
#声明一个 realm
#声明一个realm
myRealm1=com.zc.shiro.demo2.MyRealm
myRealm2=com.zc.shiro.demo2.MyRealm
#指定securityManager的realms实现
securityManager.realms=$myRealm1,$myRealm2
securityManager 会按照 realms 指定的顺序进行身份认证。此处我们使用显示指定顺序的方式指定了 Realm 的顺序,如果删除“securityManager.realms= m y R e a l m 1 , myRealm1, myRealm1,myRealm2”,那么 securityManager 会按照 realm 声明的顺序进行使用(即无需设置 realms 属性,其会自动发 现),当 我 们 显 示 指 定 realm 后 , 其 他 没 有 指 定 realm 将被忽略 , 如“securityManager.realms=$myRealm1”,那么 myRealm2 不会被自动设置进去。
2.5 Shiro默认提供的Realm
以后一般继承 AuthorizingRealm(授权)即可;其继承了 AuthenticatingRealm(即身份验证),而且也间接继承了 CachingRealm(带有缓存实现)。其中主要默认实现如下:
org.apache.shiro.realm.text.IniRealm:[users]部分指定用户名/密码及其角色;[roles]部分指定角色即权限信息;
org.apache.shiro.realm.text.PropertiesRealm:user.username=password,role1,role2 指定用户名/密码及其角色;role.role1=permission1,permission2 指定角色及权限信息;
org.apache.shiro.realm.jdbc.JdbcRealm:通过 sql 查询相应的信息,如“select password from users where username = ?”获取用户密码,“select password, password_salt from users where username = ?”获取用户密码及盐;“select role_name from user_roles where username = ?”
获取用户角色;“select permission from roles_permissions where role_name = ?”获取角色对应的权限信息;也可以调用相应的 api 进行自定义 sql;