前言
本章讲解Shiro的异常和JdbcRealm的相关知识
方法
1.回顾
在之前,我们完成了shiro的登陆验证,不知道大家有没有试过写错密码或者用户名会出现什么情况?
是会出现诸如“用户登陆失败!”的字眼吗?显然不是的!!他将会抛出异常。
还有,我们是通过在shiro配置文件中配置users来进行用户的认证,那么大多数情况下,我们都是在数据库中进行比对,验证登录。那么如何来使用数据库表中的数据来做登录的认证呢?接下来将会讲到这个问题。
2.Shiro异常
在Shiro中,异常分为如下几类:
总的异常为:AuthenticationException:认证异常
AuthenticationException又分为两大异常:AccountException:账户异常,CredentialsException:凭证异常,UnsupportedTokenException:不支持的Token异常
AccountException:
- ConcurrentAccessException:并发访问异常,如多个用户一起访问
- DisabledAccountException:不可用的账号异常,它的下面还有一个子类(LockedAccountException 账户锁定异常)
- ExcessiveAttemptsException :认证次数过多异常
- UnknownAccountException :未知账号异常
CredentialsException:
- IncorrectCredentialsException:凭证错误异常
- ExpiredCredentialsException:凭证过期异常
综上所述:我们需要使用try-catch进行异常的捕获,更改之前的代码如下:
package cn.edu.ccut.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
/**
* @Auther:jwang
* @Date:2019/5/8
* @Description:cn.edu.ccut.test
* @Version 1.0
**/
public class Authentication {
public static void main(String [] args){
//创建SecurityManager工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//通过SecurityManager工厂获取SecurityManager实例
SecurityManager securityManager = factory.getInstance();
//将SecurityManager对象设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//通过SecurityUtils获取主体Subject
Subject currentUser = SecurityUtils.getSubject();
//假设传入的用户名密码为admin和123
UsernamePasswordToken token = new UsernamePasswordToken("admin", "1231");
//进行用户身份验证
try {
currentUser.login(token);
//如果用户认证成功
if (currentUser.isAuthenticated()) {
System.out.println("用户登录成功!");
}
}catch (AuthenticationException e){
System.out.println("用户登录失败!");
}
}
}
可见,我们输入了错误的密码,执行结果如下:
3.JdbcRealm
回忆一下这个图片,我们知道shiro给我们提供了很多的Realms来进行用户的校验,本次我们就学习其中的JDBC Realm
观察org.apache.shiro.realm.jdbc.JdbcRealm类我们知道,要想进行Jdbc验证,我们需要创建users表,并且其中username、password、password_salt字段是必不可少的!
上面的图片是 JdbcRealm.java源码的部分,其中写死了一些SQL。
1)创建指定的表和字段
2)配置shiro.ini文件
首先,我们需要引入JdbcRealm
我们进入JdbcRealm源码中可以发现,其需要一个数据源。
这里我们只要使用市面上常用的连接池就可以了,我这里使用c3p0连接池了。
引入c3p0和oracle驱动相关的jar包:
配置文件更改为如下:
3)编写Java测试代码
package cn.edu.ccut.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.mgt.SecurityManager;
/**
* @Auther:jwang
* @Date:2019/5/8
* @Description:cn.edu.ccut.test
* @Version 1.0
**/
public class Authentication {
public static void main(String [] args){
//创建SecurityManager工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//通过SecurityManager工厂获取SecurityManager实例
SecurityManager securityManager = factory.getInstance();
//将SecurityManager对象设置到运行环境中
SecurityUtils.setSecurityManager(securityManager);
//通过SecurityUtils获取主体Subject
Subject currentUser = SecurityUtils.getSubject();
//假设传入的用户名密码为admin和123
UsernamePasswordToken token = new UsernamePasswordToken("sa", "sa");
//进行用户身份验证
try {
currentUser.login(token);
//如果用户认证成功
if (currentUser.isAuthenticated()) {
System.out.println("用户登录成功!");
}
}catch (AuthenticationException e){
System.out.println("用户登录失败!");
}
}
}
测试结果如下:
注意观察,我们使用了users表中的一行数据 :sa/sa
可见,我们成功的实现了JdbcRealm!