shiro的作用
shiro是一个安全框架。主要可以帮助我们解决程序开发中认证和授权的问题。上次做的权限系统,权限控制的粒度到模块级别了,如果只要能看到操作的菜单,就能操作菜单下所有的功能。以后这种权限设计模式,可能不太好满足什么的需求的需要?以后项目中,有坑你权限粒度控制的更细,有可能要控制到模块下的按钮级别,更有甚者,控制到数据的级别。以后为了方便各种各样的常用的权限管理需求的实现。我们有必要使用了比较好的安全框架。早期的Spring Security作为一个比较完善的安全框架比较火,但是spring security学习成本比较高。之后又出现了一个shiro的安全框架,学习成本降低了很多。而且基本的功能也比较完善。shiro也提供很多其他的功能:
shiro的架构
Subject:主题 被验证的对象,一般指的当前用户对象。但是不仅仅可以指当前用户对象,还可以是是其他东西,
线程等等。spring mvc中一个一个的用户的请求。
SecurityManager:安全认证管理器。是shiro的核心,会在安全认证管理器中所做所有的认证操作。类似于之前
spring mvc中的前端控制器(DispacherServlet)
Realm: 域的意思。负责访问安全认证数据。shiro 框架并不存储安全认证数据,安全认证数据需要用户自己存
储。shiro支持很多的Realm实现,也就 是说安全认证数据我们可以放到数据库中,也可以放到文件中等等。
可以把realm理解为以前web项目中的dao层。
shiro的认证
要做一个最简单的shiro的框架。实现的功能:用户的登录身份认证。用户如果用户名和密码都输入正确,认证成功,否则认证失败。
第一步,新建maven项目,导入shiro的jar包
现在使用的maven项目还是一个简单的java项目,暂时不使用web项目。
commons-logging commons-logging 1.0.4 org.apache.shiro shiro-core 1.2.3
第二步,创建shiro的认证文件
这次我们需要把用户的认证信息放到认证文件中。在resources下面建立shiro.ini:
#声明用户的对象[users]#=号前面是用户名 后面是密码zhang=123456li=654321
第三步,创建测试类
/*** 测试shiro身份认证*/public class Test01 {public static void main(String[] args) {//创建生成SecurityManager的工厂类对象Factoryfactory = new IniSecurityManagerFactory("classpath:shiro.ini");//创建SecurityManager对象SecurityManager securityManager = factory.getInstance();//把SecurityManager对象设置给SecurityUtils对象SecurityUtils.setSecurityManager(securityManager);//获取验证的主题,主题是用户对象Subject subject = SecurityUtils.getSubject();//声明要比对的用户名和密码的用户对象 相当于之前前台传过来的要校验的用户登录的信息UsernamePasswordToken token = new UsernamePasswordToken("zhansdd","123");try {//进行用户校验subject.login(token);System.out.println("校验成功");}catch (UnknownAccountException e){System.out.println("您输入的用户名不存在");}catch (IncorrectCredentialsException e){System.out.println("您输入的密码不正确");}catch (AuthenticationException e){System.out.println("校验失败");}//退出登录subject.logout();}}
realm
realm是用来读取认证的数据,上一个例子的认证的数据是存储在配置文件中的,一般项目认证数据都不会存到配
置文件中,一般在数据中,所以针对这种情况 我们就需要自定义realm。
自定义realm
第一步,声明自定义realm
/*** 自定义realm1*/public class MyRealm implements Realm {//设置本realm的名称public String getName() {return "MyRealm1";}//设置本realm支持什么样的数据校验public boolean supports(AuthenticationToken authenticationToken) {return authenticationToken instanceof UsernamePasswordToken;}//获取认证信息public AuthenticationInfo getAuthenticationInfo(AuthenticationToken authenticationToken) throwsAuthenticationException {//获取用户传递过来的用户名和密码String username = (String)authenticationToken.getPrincipal();String password = new String((char[])(authenticationToken.getCredentials()));//根据用户名和密码查询数据库,看看能不能查询到数据if(username.equals("zhangsan")&&password.equals("123456")){return new SimpleAuthenticationInfo(username,password,this.getName());}else{//校验失败 抛出校验失败异常throw new AuthenticationException("用户名或者密码错误");}}}
第二步,在shiro的主配置文件中声明我们自定义的realm
创建shiro的主配置文件shiro-custom.ini:
#声明自定义的realmmyRealm1=com.aaa.shiro.realm.MyRealm#设置安全管理器使用我们自定义的realmsecurityManager.realms=$myRealm1
第三步,测试
/*** 测试shiro身份认证 自定义realm*/public class Test02 {public static void main(String[] args) {//创建生成SecurityManager的工厂类对象Factoryfactory = new IniSecurityManagerFactory("classpath:shiro-custom.ini");//创建SecurityManager对象SecurityManager securityManager = factory.getInstance();//把SecurityManager对象设置给SecurityUtils对象SecurityUtils.setSecurityManager(securityManager);//获取验证的主题,主题是用户对象Subject subject = SecurityUtils.getSubject();//声明要比对的用户名和密码的用户对象 相当于之前前台传过来的要校验的用户登录的信息UsernamePasswordToken token = new UsernamePasswordToken("zhangsan123","123456");try {//进行用户校验subject.login(token);System.out.println("校验成功");}catch (UnknownAccountException e){System.out.println("您输入的用户名不存在");}catch (IncorrectCredentialsException e){System.out.println("您输入的密码不正确");}catch (AuthenticationException e){System.out.println("校验失败");}//退出登录subject.logout();}}
JdbcRealm
jdbcRealm的实现允许我们从一个数据源中读取认证的数据,只需要简单的配置即可。
假如要从oracle数据库中读取认证数据
第一步,在oracle中创建用户认证需要的表
JdbcRealm默认会找数据库中名称为Users的表进行查询,Users必须要有username列,password列。
第二步,引入oracle的驱动包,数据库连接池实现的包dbcp
第三步,在shiro主配置文件中配置JdbcRealm
在resources下面创建shiro-jdbcrealm.ini:
#声明数据源dataSource=org.apache.commons.dbcp.BasicDataSource#声明数据源的一些链接的属性dataSource.driverClassName=oracle.jdbc.driver.OracleDriverdataSource.url=jdbc:oracle:thin:@localhost:1521:orcldataSource.username=scottdataSource.password=tiger#声明jdbcrealmjdbcrealm=org.apache.shiro.realm.jdbc.JdbcRealm#声明jdbcrealm需要用到的数据源属性jdbcrealm.dataSource=$dataSource##设置安全管理器使用的jdbcrealmsecurityManager.realms=$jdbcrealm
第四步,测试
/*** 测试shiro身份认证 自定义realm*/public class Test03 {public static void main(String[] args) {//创建生成SecurityManager的工厂类对象Factoryfactory = new IniSecurityManagerFactory("classpath:shiro-jdbcrealm.ini");//创建SecurityManager对象SecurityManager securityManager = factory.getInstance();//把SecurityManager对象设置给SecurityUtils对象SecurityUtils.setSecurityManager(securityManager);//获取验证的主题,主题是用户对象Subject subject = SecurityUtils.getSubject();//声明要比对的用户名和密码的用户对象 相当于之前前台传过来的要校验的用户登录的信息UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123456");try {//进行用户校验subject.login(token);System.out.println("校验成功");}catch (UnknownAccountException e){System.out.println("您输入的用户名不存在");}catch (IncorrectCredentialsException e){System.out.println("您输入的密码不正确");}catch (AuthenticationException e){e.printStackTrace();System.out.println("校验失败");}//退出登录subject.logout();}}