Java环境下shiro的测试

1.导入依赖的核心jar包

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>

2.认证程序

2.1 构建users配置文件 xxx.ini doGetAuthenticationInfo方法从该配置文件中获取数据与token中比对

[users]
test=123456
lisi=123456

测试程序

public class TestShiro {
public static void main(String[] args) {
//获取安全管理器工厂
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
//获取安全管理器
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
//set认证器
SecurityUtils.setSecurityManager(securityManager);
//subject发起认证,获取subject
Subject subject = SecurityUtils.getSubject();
AuthenticationToken authenticationToken = new UsernamePasswordToken("test","123456"); //认证失败会抛出异常 密码:CredentialsException 账户:UnknownAccountException
try {
subject.login(authenticationToken);
} catch (AuthenticationException e) {
e.printStackTrace();
} //当前subject是否认证通过
boolean authenticated = subject.isAuthenticated();
System.out.println(authenticated);
}
}

认证流程:

token携带身份和凭证信息--->subject发起认证--->SimpleAccountRealm(doGetAuthenticationInfo)获取配置文件中的用户信息---->CredentialsMatcher接口的实现类SimpleCredentialsMatcher:doCredentialsMatch方法对配置文件中的信息与token携带的信息进行比对--->认证成功或者失败。

3.Shiro框架中的关键对象:

AuthenticatingRealm  //抽象类
//3.关键属性 该属性为凭证匹配器
CredentialsMatcher credentialsMatcher;
//1.该方法为抽象方法 其作用使用来获取数据
protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken var1) throws AuthenticationException;
SimpleAccountRealm
//2.实现了AuthenticatingRealm抽象方法,用来获取配置文件中的用户信息,该类不做数据比对
SimpleCredentialsMatcher
//4.shiro中默认的凭证匹配器
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenCredentials = this.getCredentials(token);
Object accountCredentials = this.getCredentials(info);
return this.equals(tokenCredentials, accountCredentials);
}

必须要知道的类与接口,不然很难理解自定义Realm时属性为什么设置,使用哪种实现类方法等等:

以下代码或者截图贴出最重要的地方.

类继承关系

AuthenticatingRealm类

abstract class AuthenticatingRealm{
//凭证匹配器 接口,其实现类做数据比对
private CredentialsMatcher credentialsMatcher;
//获取配置文件中的用户信息
protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken var1) throws AuthenticationException;
}

该抽象方法返回类型AuthenticationInfo接口:

AuthorizingRealm类 抽象方法后面测试授权时使用

abstract class AuthorizingRealm{
//
//该抽象方法 获取数据 获取授权的数据
protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection var1);
}

该抽象方法返回类型AuthorizationInfo接口:

CredentialsMatcher凭证匹配器接口:

其中:SimpleCredentialsMatcher是shiro中默认的凭证匹配器,其子类Hashxxx等都是做加密认证时使用

4.开发自定义Realm

public class MyRealm extends AuthenticatingRealm {
//实现抽象方法doGetAuthenticationInfo
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
String principal =(String) authenticationToken.getPrincipal();
//查库取回User对象
SqlSession sqlSession = null;
try {
sqlSession = MySqlSession.getSqlSession();
} catch (IOException e) {
e.printStackTrace();
}
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserByUserName(principal);
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(principal,user.getPassword(),this.getName());
return authenticationInfo;
}
}

4.1通知shiro使用自定义realm

[main]
#自定义 realm
customRealm=com.nyist.test.MyRealm
#将realm设置到securityManager
securityManager.realms=$customRealm

注意:需要导入一个jar

<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>

5.shiro的加密认证方式

5.1.使用shiro提供的Md5Hash类为一个字符串加密进行测试

public class TestMD5 {
public static void main(String[] args) {
Md5Hash hash = new Md5Hash("123456","salt",1024);
String s = hash.toHex();
System.out.println(s);
//a18d2133f593d7b0e3ed488560404083
}
}

5.2.修改配置文件,加入凭证匹配器的相关配置

[main]
#自定义凭证匹配器
hashedCredentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#凭证匹配器通知AuthenticatingRealm,由于自定义realm继承了AuthenticatingRealm,直接设置已有的MyRealm属性即可 #自定义 realm
customRealm=com.nyist.test.MyRealm
customRealm.credentialsMatcher=$hashedCredentialsMatcher
hashedCredentialsMatcher.hashAlgorithmName=MD5
hashedCredentialsMatcher.hashIterations=1024 #将realm设置到securityManager .realms使用set方式赋值
securityManager.realms=$customRealm

坑:Caused by: java.lang.IllegalStateException: Required 'hashAlgorithmName' property has not been set. This is required to execute the hashing algorithm.

HashedCredentialsMatcher类中set方法非常规,set方法为:setHashAlgorithmName

为什么这么设置凭证匹配器?

自定义MyRealm extends AuthorizingRealm,实现两个抽象方法

AuthenticationInfo doGetAuthenticationInfo()来自于AuthenticatingRealm类,获取认证数据

AuthorizationInfo doGetAuthorizationInfo()来自于AuthorizingRealm类,获取授权数据

public class MyRealm extends AuthorizingRealm {

    @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
String principal =(String) authenticationToken.getPrincipal();
//userDao.queryUserByUserName
SqlSession sqlSession = null;
try {
sqlSession = MySqlSession.getSqlSession();
} catch (IOException e) {
e.printStackTrace();
}
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserByUserName(principal); /*
* ByteSource.Util.bytes("salt") 盐字段来自数据库,凭证匹配器不能写死盐值
* 安全管理器可以获取到AuthenticationInfo中的盐值 对用户界面的凭证加密
* */
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(principal,user.getPassword(),ByteSource.Util.bytes("salt"),this.getName());
return authenticationInfo;
} @Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取身份信息 Principal用户名、手机号、邮箱地址等 一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
/*
* 用户----角色----权限
* 中间表 中间表
* */
//由primaryPrincipal查库--->获得角色info ---->获取权限info
SqlSession sqlSession = null;
try {
sqlSession = MySqlSession.getSqlSession();
} catch (IOException e) {
e.printStackTrace();
}
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.queryUserByUserName(primaryPrincipal);
//测试基于角色的授权
/*if (primaryPrincipal.equals(user.getUsername())){
// class SimpleAuthorizationInfo implements AuthorizationInfo
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.addRole("super");
return authorizationInfo;
}*/
//测试基于资源的授权
if(primaryPrincipal.equals(user.getUsername())){
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.addStringPermission("user:delete");
authorizationInfo.addStringPermissions(Arrays.asList("admin:delete","admin:add"));
return authorizationInfo;
}
return null;
}
}

一张图看懂认证授权关系:

授权的api

  • 基于角色

                //判断当前主体是否包含此角色
    boolean b = subject.hasRole("super");
    List<String> list = Arrays.asList("super", "admin");
    //判断当前主体是否包含某个角色
    boolean[] booleans = subject.hasRoles(list);
    //判断当前主体是否包含全部的角色
    boolean b = subject.hasAllRoles(list);
  • 基于资源

                boolean b = subject.isPermitted("admin:delete");
    String[] strs={"admin:delete", "admin:add"};
    boolean[] permitted = subject.isPermitted(strs);
    boolean permittedAll = subject.isPermittedAll(strs);

资源权限的标识符

权限字符串的规则是:“资源标识符:操作:资源实例标识符”,意思是对哪个资源的哪个实例具有什么操作,“:”是资源/操作/实例的分割符,权限字符串也可以使用*通配符。

例子:

  • 用户创建权限:user:create,或user:create:*
  • 用户修改实例001的权限:user:update:001
  • 用户实例001的所有权限:user:*:001

Java环境下shiro的测试-认证与授权的更多相关文章

  1. NLPIR分词工具的使用(java环境下)

    一.NLPIR是什么? NLPIR(汉语分词系统)由中科大张华平博士团队开发,主要功能包括:中文分词,词性标注,命名实体识别,用户词典功能,详情见官网:http://ictclas.nlpir.org ...

  2. Java 环境下使用 AES 加密的特殊问题处理

    在 Java 环境下使用 AES 加密,在密钥长度和字节填充方面有一些比较特殊的处理. 1. 密钥长度问题 默认 Java 中仅支持 128 位密钥,当使用 256 位密钥的时候,会报告密钥长度错误 ...

  3. 《安卓网络编程》之第一篇 java环境下模拟客户端、服务器端

    1.Socket简介 在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket通常用来实现客户方和服务方的连接.Socket是TCP/IP协议的一个 ...

  4. 这是关于FastJson的一个使用Demo,在Java环境下验证的

    public class User { private int id; private String name; public int getId() { return id; } public vo ...

  5. 1、 Shiro框架:认证,授权(验权 2. Shiro框架实现权限控制方式:

    1. Shiro框架:认证,授权(验权) a) 认证逻辑:applicationCode—>通过工具类获取subject对象,调用login方法参数令牌信息->安全管理器------> ...

  6. 用户登录安全框架shiro—用户的认证和授权(一)

     ssm整合shiro框架,对用户的登录操作进行认证和授权,目的很纯粹就是为了增加系统的安全线,至少不要输在门槛上嘛. 这几天在公司独立开发一个供公司内部人员使用的小管理系统,客户不多但是登录一直都是 ...

  7. spring-security-4 (5)spring security Java配置实现自定义表单认证与授权

    前面三篇讲解了spring security的搭建以及简单的表单认证与授权原理.本篇将实现我们自定义的表单登录与认证.  本篇不会再讲项目的搭建过程,因为跟第二节的搭建如出一辙.本篇也不会将项目中所有 ...

  8. 【转载】Selenim入门环境的搭建--Java环境下的Java Maven Project

    一.开发环境 操作系统: xp win7 win8 win10都可以 JDK: 1.6或者1.7 下载地址 JDK1.7下载 Eclipse: 官网下载比较新的版本,建议下载EE的版本  eclips ...

  9. 如何在Java 环境下使用 HTTP 协议收发 MQ 消息

    1. 准备环境在工程 POM 文件添加 HTTP Java 客户端的依赖. <dependency> <groupId>org.eclipse.jetty</groupI ...

随机推荐

  1. Ajax - 汇总

    1,什么是ajax? 为什么要使用ajax? 1.ajax是"asynchornous javascript and xml "的缩写,指一种创建交互式网页应用的网页开发技术. 2 ...

  2. Spring-test单元测试

    <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test& ...

  3. _ai_creature

  4. 改变input中的placeholder样式

    1.input[placeholder]{ color:#d5d5d5; } 2.input::-moz-placeholder { color: #d5d5d5; } input:-ms-input ...

  5. 下载安装tomcat和jdk,配置运行环境,与Intellij idea 2017关联

    第一篇博客,最近公司要用java和jsp开发新的项目,第一次使用Intellij idea 2017,有很多地方需要一步步配置,有些按照网上的教程很快就配置好了,有的还是琢磨了一会儿,在这里做一个记录 ...

  6. leetcode 7-> Reverse Integer(32-bit signed integer)

    class Solution(object): def reverse(self, x): """ :type x: int :rtype: int "&quo ...

  7. Mysql 强行Kill 连接

    BEGIN ; ; ; DO KILL @Temp; ; END WHILE ; END

  8. R语言网页爬虫

    R 是统计计算和数据分析的利器.给定一个数据集,利用前几章介绍到的 R 中灵活的数据结构或高性能计算,我们可以很方便地进行数据转换.建模和数值分析.一般来说,商业数据库会将数据以表格的形式很好地组织起 ...

  9. django信号 signal

    django自带一套信号机制来帮助我们在框架的不同位置之间传递信息.也就是说,当某一事件发生时,信号系统可以允许一个或多个发送者(senders)将通知或信号(signals)发送给一组接受者(rec ...

  10. 使用ajax判断登录用户名

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Register.aspx. ...