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. 将linux下的rm命令改造成移动文件至回收站

    将linux下的rm命令改造成移动文件至回收站 rm是Linux下文件删除的命令,它是Linux下非常强大却又非常危险的一条命令,特别是rm -rf有时候强大到让你欲哭无泪,当你想清除当前目录下的所有 ...

  2. POJ3204 Ikki's Story - Road Reconstruction 网络流图的关键割边

    题目大意:一个有源有汇的城市,问最少增加城市中的多少道路可以增加源到汇上各个路径上可容纳的总车流量增加. 网络流关键割边集合指如果该边的容量增加,整个网络流图中的任意从原点到汇点的路径的流量便可增加. ...

  3. hdoj--1864--最大保险额(背包)

    最大报销额 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Subm ...

  4. <T extends Serializable>这是什么意思呢?看明白这个,你的问题就自然而然的明白了!

    1.转自:https://blog.csdn.net/liwenqiang758/article/details/8131185 自己动手丰衣足食!!! 泛型是Java SE 1.5的新特性,泛型的本 ...

  5. md5 c# unicode 互换(原创)

    php 代码 $input='中国'; $result= md5($input); $temp=iconv("UTF-8", "UTF16LE", $input ...

  6. POJ 3258 (NOIP2015 D2T1跳石头)

    河中跳房子 总时间限制: 1000ms 内存限制: 65536kB 描述 每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一个岩石跳到另一个岩石.这项激动人心的活动在一条长长的笔直河道中进行, ...

  7. Web启动,停止Windows服务

    When you grow stronger,the world become more dangerous.当你变得越强大,这个世界反而会变得越危险. ServiceModel.cs代码: publ ...

  8. Javascript中数组重排序方法详解

    在数组中有两个可以用来直接排序的方法,分别是reverse()和sort().下面通过本文给大家详细介绍,对js 数组重排序相关知识感兴趣的朋友一起看看吧. 1.数组中已存在两个可直接用来重排序的方法 ...

  9. JS学习笔记(一)JS处理JSON数据

    [摘抄]将JSON字符串转换为json对象的方法.在数据传输过程中,json是以文本,即字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键.例如:J ...

  10. Android java处理保留小数点后几位

    方式一: 四舍五入  double   f   =   111231.5585;  BigDecimal   b   =   new   BigDecimal(f);  double   f1   = ...