Shiro教程之二Shiro.ini认证和授权
1,Shiro.ini文件的说明
1. ini (InitializationFile) 初始文件.Window系统文件扩展名.
2. Shiro 使用时可以连接数据库,也可以不连接数据库.
2.1 如果不连接数据库,可以在shiro.ini中配置静态数据
2,Shrio.ini文件的组成部分
1,[main] :定义全局变量
[main] securityManager.属性=值 <property name=”属性名” value=”” myobj=com.bjsxt.Obj <bean id=”myobj” class=”com.bjsxt.Obj” securityManager.对象属性=$myobj <property name=”属性名” ref=” myobj”2,[users] :定义用户名和密码
[users] # 定义用户名为zhangsan 密码为zs zhangsan=zs # 定义用户名lisi密码为lisi同时具有role1和role2两个角色 lisi=lisi,role1,role23,[roles]: 定义角色
[roles] role1=user:query,权限名2 role2=权限3,权限44,[urls] : 定义哪些内置urls生效.在web应用时使用.
[urls] #url地址=内置filter或自定义filter # 访问时出现/login的url必须去认证.支持authc对应的Filter /login=authc # 任意的url都不需要进行认证等功能. /** = anon # 所有的内容都必须保证用户已经登录. /**=user # url abc 访问时必须保证用户具有role1和role2角色. /abc=roles[“role1,role2”] /login.html*=anon /loginOut*=logout /**= authc 所有URL必须认证通过之后才能放行 一般放到最后
3,【掌握】Shiro.ini实现认证和授权
1,基本概念
1,身份验证 即在应用中谁能证明他就是他本人。一般提供如他们的身份ID 一些标识信息来 表明他就是他本人,如提供身份证,用户名/密码来证明。 在 shiro 中,用户需要提供principals (身份)和credentials(证明)给shiro,从而应用能 验证用户身份: 2,principals 【/'prɪnsəpl】 身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。 一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号。 3,credentials 【/krə'dɛnʃlz/】 证明/凭证,即只有主体知道的安全值,如密码/数字证书等。 最常见的principals和credentials组合就是用户名/密码了。接下来先进行一个基本的身份认证。
2,认证流程
其它就是使用Shrio的认证来取代我们传统的登陆方式
3,入门程序实现认证
1. 创建项目(引入jar包或maven依赖)
2. 创建shiro.ini(类路径或最后可以编译到类路径的目录)
#配置用户 [users] zhangsan=123456 lisi=123456 wangwu=123456
3. 写代码测试 (认证)
package com.cc8w.test; import com.cc8w.shiro.ShiroRealm; import org.apache.log4j.Logger; 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.authz.AuthorizationException; import org.apache.shiro.authz.UnauthenticatedException; import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.apache.shiro.mgt.SecurityManager; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.Arrays; /** * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) public class TestShiro { private static Logger logger = Logger.getLogger(TestShiro.class); @Autowired private ShiroRealm shiroRealm; public static void main(String[] args) { TestShiro ts = new TestShiro(); ts.testAuth(); } //一,登录测试(基于ini文件,注释掉shiro的main区域,因为此区域配置了非ini文件[自定义Realm]的设置) @Test public void testlogin(){ //1.创建一个安全管理器的工厂 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); //2.在工厂中获取安全管理器 SecurityManager securityManager = factory.getInstance(); //3.将securityManager绑定到运行环境 SecurityUtils.setSecurityManager(securityManager); //4.获取Subject对象(将要登录的用户) Subject subject = SecurityUtils.getSubject(); //5.获取要登录用户的token,客户端传递过来的用户名和密码 String username = "zhangsan",password="123456"; UsernamePasswordToken token = new UsernamePasswordToken(username,password); try{ subject.login(token); logger.info("登录了"); }catch (IncorrectCredentialsException e ){ logger.info("密码不正确"); logger.info(e); }catch (UnknownAccountException e) { System.out.println("没有这个帐号"); }catch (AuthenticationException e) { e.printStackTrace(); } //如果登录成功了,可以获取subject中各种状态了 Boolean isAuth = subject.isAuthenticated(); logger.info(isAuth); try { subject.checkRole("roles"); }catch (UnauthenticatedException e){ logger.info("没有这个角色"); e.printStackTrace(); } } }
相关方法总结
1, 注意Subject的或取方式
2, 注意使用异常方式确定登陆是否成功
==========================
4,【掌握】shiro.ini实现授权
1,授权概述
授权,也叫访问控制,即在应用中控制谁能访问哪些资源(如访问页面/编辑数据/页面操作
等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限(Permission)、
角色(Role)。
2,关键对象介绍
1,主体 主体,即访问应用的用户,在Shiro中使用Subject代表该用户。用户只有授权后才允许访问相应的资源。 2,资源 在应用中用户可以访问的任何东西,比如访问JSP 页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。 3,权限 安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即权限表示在应用中用户能不能访问某个资源,
如:访问用户列表页面查看/新增/修改/删除用户数据(即很多时候都是CRUD(增查改删)式权限控制)打印文档等等。。。 4,角色 角色代表了操作集合,可以理解为权限的集合,一般情况下我们会赋予用户角色而不是权限,即这样用户可以拥有一组权限,赋予权限时比较方便。
典型的如:项目经理、技术总监、CTO、开发工程师等都是角色,不同的角色拥有一组不同的权限。
3,授权流程
4,相关方法说明
1 subject.hasRole(“”); 判断是否有角色 2 subject.hashRoles(List);分别判断用户是否具有List中每个内容 3 subject.hasAllRoles(Collection);返回boolean,要求参数中所有角色用户都需要具有. 4 subject.isPermitted(“”);判断是否具有权限.
5,修改shiro.ini
#配置用户 [users] zhangsan=123456,role1 lisi=123456,role2,role4 wangwu=123456,role3 zhaoliu=123456,role4 #配置角色和权限 [roles] role1=user:query,user:add,user:update,user:delete,user:export role2=user:query role3=user:query,user:add role4=user:query,user:export
6,权限标识符号规则
权限标识符号规则:资源:操作:实例(中间使用半角:分隔) user:create:01 表示对用户资源的01实例进行create操作。 user:create:表示对用户资源进行create操作,相当于user:create:*,对所有用户资源实例进行create操作。 user:*:01 表示对用户资源实例01进行所有操作。
7,测试代码 (因为测试授权时必须登录,所以下认证登录)
package com.cc8w.test; import com.cc8w.shiro.ShiroRealm; import org.apache.log4j.Logger; 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.authz.AuthorizationException; import org.apache.shiro.authz.UnauthenticatedException; import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.apache.shiro.mgt.SecurityManager; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.Arrays; /** * */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) public class TestShiro { private static Logger logger = Logger.getLogger(TestShiro.class); @Autowired private ShiroRealm shiroRealm; public static void main(String[] args) { TestShiro ts = new TestShiro(); ts.testAuth(); } //一,登录测试(基于ini文件,注释掉shiro的main区域,因为此区域配置了非ini文件[自定义Realm]的设置) @Test public void testlogin(){ //1.创建一个安全管理器的工厂 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); //2.在工厂中获取安全管理器 SecurityManager securityManager = factory.getInstance(); //3.将securityManager绑定到运行环境 SecurityUtils.setSecurityManager(securityManager); //4.获取Subject对象(将要登录的用户) Subject subject = SecurityUtils.getSubject(); //5.获取要登录用户的token,客户端传递过来的用户名和密码 String username = "zhangsan",password="123456"; UsernamePasswordToken token = new UsernamePasswordToken(username,password); try{ subject.login(token); logger.info("登录了"); }catch (IncorrectCredentialsException e ){ logger.info("密码不正确"); logger.info(e); }catch (UnknownAccountException e) { System.out.println("没有这个帐号"); }catch (AuthenticationException e) { e.printStackTrace(); } //如果登录成功了,可以获取subject中各种状态了 Boolean isAuth = subject.isAuthenticated(); logger.info(isAuth); try { subject.checkRole("roles"); }catch (UnauthenticatedException e){ logger.info("没有这个角色"); e.printStackTrace(); } } //二.授权验证(基于ini文件,注释掉shiro的main区域,因为此区域配置了非ini文件[自定义Realm]的设置) @Test public void testAuth(){ String username = "zhangsan",password="123456"; //1.创建securityManager工厂SecurityManager JDK也有这个类,在java.lang包,注意不要使用jdk里面的类 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); //2,从工厂中获取SecurityManager SecurityManager securityManager = factory.getInstance(); //3,把当前的SecurityManager绑定到当前线程中 SecurityUtils.setSecurityManager(securityManager); //4,取出当前的Subject Subject subject = SecurityUtils.getSubject(); //5.创建token用于认证 客户端传递过来的用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken(username,password); //6.登录认证 try{ subject.login(token); System.out.println("登录成功"); }catch (IncorrectCredentialsException e){ System.out.println("密码不正确"); }catch (UnknownAccountException e){ System.out.println("无此账号"); }catch (AuthenticationException e) { e.printStackTrace(); } System.out.println("认证状态:"+subject.isAuthenticated()); //7.授权 基于角色授权 基于资源的授权 //7.1 基于角色授权 boolean isRole1 = subject.hasRole("role1"); System.out.println("这是授权单个: "+isRole1); boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1","role2","role3")); System.out.println("这是多个授权:" + hasAllRoles); // 使用check方法进行授权,如果授权不通过会抛出异常 // subject.checkRole("role13"); // 7.2 基于资源的授权 // isPermitted传入权限标识符 boolean isPermitted = subject.isPermitted("user:query"); System.out.println("单个权限判断user:query->"+isPermitted); boolean isPermittedAll = subject.isPermittedAll("user:query","user:add","user:del"); System.out.println("多个权限判断"+isPermitted); // 使用check方法进行授权,如果授权不通过会抛出异常 try{ subject.checkPermission("items:create:1"); }catch (UnauthorizedException e){ // e.printStackTrace(); System.out.println("没有这个权限"); } } }