shiro在应用程序中的使用是用Subject为入口的, 最终subject委托给真正的管理者ShiroSecurityMannager

Realm是Shiro获得身份认证信息和来源信息的地方(所以这里是我们实现的)我们只要继承他的实现类重写方法就好了,AuthorizingRealm

身份认证过程

自定义realm代码

public class myRealm  extends AuthorizingRealm  {
        //realm的名称
	@Override
	public String getName() {
		// TODO Auto-generated method stub
		return "myRealm";
	}
        //验证token是否是有效的token
	@Override
	public boolean supports(AuthenticationToken arg0) {
		// TODO Auto-generated method stub
		return arg0 instanceof UsernamePasswordToken;
	}
        //授权获得用户权限信息的方法
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
		info.addRole("321");
		info.addRole("3332");
		info.addStringPermission("333");
		info.addStringPermission("555");
		info.addObjectPermission(new WildcardPermission("44"));
		// TODO Auto-generated method stub
		return info;
	}
         //认证获取用户身份信息的方法
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		 UsernamePasswordToken loginToken=(UsernamePasswordToken)token;
		   String password=new String(loginToken.getPassword());
		   System.out.println(password);
		   System.out.println(loginToken.getUsername());
		   if(loginToken.getUsername()=="zhang"&&password.equals("123")){

		   }else{
			   throw new IncorrectCredentialsException();
		   }
			// TODO Auto-generated method stub
			SimpleAuthenticationInfo info= new SimpleAuthenticationInfo(loginToken.getUsername(),password,getName());
			return info;
	}

}

  

doGetAuthorizationInfo方法是进行用户授权的时候调用的方法 用户获得当前用户的授权信息 先不管他
doGetAuthenticationInfo是当我们调用subject.login进行认证的方法 这个方法的参数token就是我们subject.login调用的
这里面我们就可以查询数据库对用户名和密码进行认证
如果认证成功将用户信息封装成SimpleAuthenticationInfo
认证失败根据几种情况抛出异常,常见的如:
DisabledAccountException(禁用的帐号)、LockedAccountException(锁定的帐号)
UnknownAccountException(错误的帐号)
ExcessiveAttemptsException(登录失败次数过多)、IncorrectCredentialsException (错误的凭证)
ExpiredCredentialsException(过期的凭证)等

shiro.ini配置

#声明一个realm
myRealm1=com.liqiang.realm.myRealm
#这里就是我们注入realm的地方
securityManager.realms=$myRealm1

实现身份认证的代码

	@Test
	public void testHelloworld() {
	    //1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
	    Factory<org.apache.shiro.mgt.SecurityManager> factory =
	            new IniSecurityManagerFactory("classpath:shiro.ini");
	    //2、得到SecurityManager实例 并绑定给SecurityUtils
	    org.apache.shiro.mgt.SecurityManager securityManager = factory.getInstance();
	    SecurityUtils.setSecurityManager(securityManager);
	    //3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
	    Subject subject = SecurityUtils.getSubject();
	    UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");  

	    try {
	        //4、登录,即身份验证
	        subject.login(token);
	    } catch (AuthenticationException e) {
	        //5、身份验证失败
	    }  

	    subject.logout();
	}

上面我们调用sbuject.login(token) 这个token封装了前端用户输入的用户名和密码

授权验证

当我们通过subject.isPermitted("user:update") 当我们判断当前用户是否拥有user:update这个权限代码的时候

会调用我们ream的 doGetAuthorizationInfo 方法获得授权信息。我们在这里面就是根据用户信息查询数据将认证信息封装

SimpleAuthorizationInfo 返回回去


   //授权获得用户权限信息的方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addRole("321");
        info.addRole("3332");
        info.addStringPermission("333");
        info.addStringPermission("555");
        info.addObjectPermission(new WildcardPermission("44"));
        // TODO Auto-generated method stub
        return info;
    }

这里通过查询数据库知道用户有321  332  这2个角色 和 333   555   44  这几个权限

WildcardPermission 这个又是什么意思呢。。通过addStringPermission  默认是用Permission的实现类封装的 如果我们又定义就用我们的封装 没有定义就用默认的WildcardPermission最终将他们保存到一个集合里面如:
public class MyPermission implements Permission {

    String permissionCode;
    public MyPermission(String name) {
        permissionCode=name;
    }

    @Override
    public boolean implies(Permission permission) {
        //自定义比较
        // TODO Auto-generated method stub
        return false;
    }

}

当我们调用subject.isPermitted("user:update")会调用将指令传达给

SecurityManager 
SecurityManager 再将指令传达给授权管理类Authorizer
Authorizer会通过reaml获得授权信息SimpleAuthorizationInfo如果我们返回的授权信息拥有角色 会调用RolePermissionResolver实现类的方法 将角色的权限追加到SimpleAuthorizationInfo(默认是没有实现的)如:
public class MyRolePermissionResolver  implements RolePermissionResolver{

    @Override
    public Collection<Permission> resolvePermissionsInRole(String roleString) {
        // TODO Auto-generated method stub
         return Arrays.asList((Permission)new MyPermission("menu:*"));
    }

这里面应该是根据角色查询权限

最终 遍历SimpleAuthorizationInfo的权限信息 (我们的权限信息都封装Permission接口实现类 调用implies方法进行比较 如果比较成功返回true 表示授权通过)自定义Permission的好处就是我们可以自定义匹配规则

注入自定义Permission和RolePerminssion的配置

[main]
authorizer=org.apache.shiro.authz.ModularRealmAuthorizer
securityManager.authorizer=$authorizer
#自定义rolePermissionResolver
rolePermissionResolver=com.liqiang.permissionResolver.MyRolePermissionResolver
authorizer.rolePermissionResolver=$rolePermissionResolver
securityManager.authorizer=$authorizer
permissionResolver=com.liqiang.permissionResolver.MyPermissionResolver
authorizer.permissionResolver=$permissionResolver
#声明一个realm
myRealm1=com.liqiang.realm.myRealm
#指定securityManager的realms实现
securityManager.realms=$myRealm1

PS:好记性不如烂笔头  希望自己回头来看一下就能回忆起来

学习文章:http://jinnianshilongnian.iteye.com/blog/2018398

Shiro身份认证授权原理的更多相关文章

  1. Apache shiro集群实现 (三)shiro身份认证(Shiro Authentication)

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  2. Shiro身份认证---转

    目录 1. Shro的概念 2. Shiro的简单身份认证实现 3. Shiro与spring对身份认证的实现 前言: Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE 环境 ...

  3. [认证授权] 5.OIDC(OpenId Connect)身份认证授权(扩展部分)

    在上一篇[认证授权] 4.OIDC(OpenId Connect)身份认证授权(核心部分)中解释了OIDC的核心部分的功能,即OIDC如何提供id token来用于认证.由于OIDC是一个协议族,如果 ...

  4. asp.net core 使用identityServer4的密码模式来进行身份认证(2) 认证授权原理

    前言:本文将会结合asp.net core 认证源码来分析起认证的原理与流程.asp.net core版本2.2 对于大部分使用asp.net core开发的人来说. 下面这几行代码应该很熟悉了. s ...

  5. Shiro学习总结(3)——Apache Shiro身份认证

    身份验证,即在应用中谁能证明他就是他本人.一般提供如他们的身份ID一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明. 在shiro中,用户需要提供principals (身份)和cre ...

  6. Shiro身份认证、盐加密

    目的: Shiro认证 盐加密工具类 Shiro认证 1.导入pom依赖 <dependency> <groupId>org.apache.shiro</groupId& ...

  7. CVE-2020-17523:Apache Shiro身份认证绕过漏洞分析

    0x01 Apache Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 0x02 漏洞简介 2021年2月1日,Apache Shiro官 ...

  8. [认证授权] 4.OIDC(OpenId Connect)身份认证授权(核心部分)

    0 目录 认证授权系列:http://www.cnblogs.com/linianhui/category/929878.html 1 什么是OIDC? 看一下官方的介绍(http://openid. ...

  9. Shiro身份认证-JdbcRealm

    Subject 认证主体 Subject认证主体包含两个信息 Principals : 身份,可以是用户名.邮箱.手机号等,用来标识一个登录主体身份. Credentials : 凭证,常见有密码,数 ...

随机推荐

  1. 当使用servlet输出json时,浏览器端jquery的ajax遇到parse error的问题

    在使用jquery的ajax进行请求发送并由服务端的servlet返回json格式的数据内容时,假设输出内容没有正确设置,会遇到client浏览器报告parse error的问题.这个问题的解决仅仅须 ...

  2. 【待解决】An internal error occurred during: "Launching baiduTest1". java.lang.NullPointerException

    编写的一个Java类,以junit运行可以正常执行,以testNG执行就报如下错误 解决方法:

  3. POJ3090 Visible Lattice Points 欧拉筛

    题目大意:给出范围为(0, 0)到(n, n)的整点,你站在原点处,问有多少个整点可见. 线y=x和坐标轴上的点都被(1,0)(0,1)(1,1)挡住了.除这三个钉子外,如果一个点(x,y)不互质,则 ...

  4. luogu4180 次小生成树Tree 树上倍增

    题目:求一个无向图的严格次小生成树(即次小生成树的边权和严格小于最小生成树的边权和) 首先求出图中的最小生成树.任意加一条树外边都会导致环的出现.我们现在目标是在树外边集合B中,找到边b∈B,a∈b所 ...

  5. ThinkPHP搜索框需要注意的事项

    1.当搜索成功后需要用到分页的时候,form表单需要用get传参 2.编码方式 当编码方式不正确的时候,使用分页类改变分页,会使搜索框里面的内容乱码 改变编码方式的方法 第一种:header(&quo ...

  6. Android网络编程随想录(1)

    本系列文章对整个Android网络编程进行了总结,包括基本的TCP/IP协议,HTTP协议,HTTPS协议,HttpClient,UrlConnection,一些网络通信的库到棉花糖新加入的OKHTT ...

  7. 外观模式(Facade)C++实现

    外观模式 意图: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一系统更加容易使用. 适用性: 1.在设计初期阶段,应该要有意识的将不同的两个层分离,比如经典的三层架 ...

  8. 修改数组数据头和尾push()、pop()和unshift()、shift()

    1.push().pop()和unshift().shift() 这两组同为对数组的操作,并且会改变数组的本身的长度及内容. 不同的是 push().pop() 是从数组的尾部进行增减,unshift ...

  9. JS中数组的一些笔记

    今天工作时碰到一个需求,有两个数组arrayChild, arrayFather, 要求: 1.往数组arrayChild中放入一个元素: 2.将当前的数组arrayChild放入arrayFathe ...

  10. [hihocoder][Offer收割]编程练习赛49

    相似颜色 #pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #includ ...