从一个案例窥探ORACLE的PASSWORD_VERSIONS

1、环境说明


ORACLE 客户端版本


11.2.0.1


ORACLE 服务端版本


12.2.0.1

2、异常现象

客户端(下文也称为Cp)访问服务端(Sp),报了一个错误:

Figure 1

以错误码为关键字在网上查找原因,有网友建议把服务器的sqlnet.ora文件中的SQLNET.ALLOWED_LOGON_VERSION_SERVER参数 和 SQLNET.ALLOWED_LOGON_VERSION_CLIENT参数改为8(原值为12)。如下图所示:

Figure 2

改过之后重新连接,糟糕,出现了新的错误:

Figure 3

可是我从其它的客户端(后来发现这些客户端版本均高于11.2.0.1)连接该Sp均没有问题。我以为是不是有什么后台程序会把输入的所有小写强制转成大写,于是我将账户密码从sys修改为SYS,然后再连接:

Figure 4

成功了。从现象上来看,似乎真的就是大小写的关系。可是真的是的吗?我现在将密码从SYS改回sys,然后再连接:

Figure 5

这回用sys作为密码登陆,也成功了。看来真正的原因,不是什么后台程序强制转换了大小写。那究竟是什么原因呢?

3、原理解释

其实,从现象上来看,变化最初是在设置了

SQLNET.ALLOWED_LOGON_VERSION_CLIENT

和SQLNET.ALLOWED_LOGON_VERSION_SERVER两个参数后产生的。那这两个参数到底起什么作用呢?

先看一下SQLNET.ALLOWED_LOGON_VERSION_CLIENT在官方文档中的说明:

Figure 6

这个参数是12C新引进的参数。它表示Cp在向Sp发送认证(authentication)申请时,所使用的最低版本的认证协议。注意此处的认证协议版本并不等同于Oracle Database的版本。那不同的认证协议版本主要区别在哪儿呢?除了协议语义上的区别,在我看来,最重要的区别在于不同认证协议的版本对应着不同的database version,而不同的database version则可能使用不同的hash算法对密码进行加密。不同的hash算法就是不同的password_version,这个可以从dba_users字典表的password_versions字段中得到说明:

Figure 7

Oracle在存储每个account的密码时,并非是明文存储,而是会将明文进行哈希加密存储,哈希加密算法即为该密码的version,即password_version。从上图Figure 7中可知,password_version实际上表示是同版本(并非完全一致,见最后的附表)的database 所提供的hash算法,例如password_version 10g就表示database 10g所提供的hash算法。如果Oracle所有的新版本都只使用新版本所特有的hash算法,那么一些较早的客户端因为还没有这些hash算法,就没法通过hash算法得到hash值,也就没法让服务器去验证这些hash值。为了解决兼容性的问题,Oracle会同时用多种hash算法(即password_version)对密码进行运算,并将多个运算结果均保留下来。在低版本客户端访问高版本的服务器时,低版本的客户端可以通报自己使用的认证协议以及使用该协议对应的hash算法所得到的密码hash值,服务器根据认证协议去查看是否存储了该协议对应的hash算法的hash值,如果存在,就比对两个hash值是否一致;如果不存在或两个hash值不一致,就报错。其流程图大致如下所示(仅代表自己的理解):

在上述密码认证流程图中,标红的子流程——"判断该账户的password_versions中是否包含client version",有一个疑问:account有哪些password version,是由什么决定的呢?这就引出了另一个参数:SQLNET.ALLOWED_LOGON_VERSION_SERVER。

关于这个参数的作用,它介绍了为这个参数设置不同的值所带来的影响,主要是对PASSWORD_VERSIONS的影响。最后附带了一张表,详细了列出了SQLNET.ALLOWED_LOGON_VERSION_SERVER设置不同值,所对应的password_versions。也说明了如果要与设置成当前值的12C数据库进行密码认证,所支持的client version。从上图可以看出,即使SQLNET.ALLOWED_LOGON_VERSION_SERVER设置为8,但生成的最低版本的password version也是10G。因此也说明,8I,9I的客户端因为没法理解10G的哈希函数,也就没法完成登陆认证。关于客户端到服务器端相互之间的兼容性如下表:

4、案例重演

  1. 在SQLNET.ALLOWED_LOGON_VERSION_SERVE=12时,为sys用户设置了密码,因此sys账户的password_versions=11G,12C

  2. 这时用client version 11.2.0.1请求登陆,因为client version 11.2.0.1的认证协议版本为11(该版本小于11.2.0.3,并没有打CPUOct2012补丁,因为认证协议版本为11),所以流程如红线1所示:

  3. 然后手动将SQLNET.ALLOWED_LOGON_VERSION_SERVE改为8,但因为只是参数变化,并没有重建密码,因此该account的实际password仍然为11G,12C,所以请求登陆的流程如红线2所示:

  4. 重新生成密码。因为是在SQLNET.ALLOWED_LOGON_VERSION_SERVE=8的情况下生成的密码,因此该account所对应的password_versions=10G,11G,12C,如下图所示:

    而该password_versions是支持client version 11.2.0.1密码认证的,所以请求登陆的流程如红线3所示:

5、认证协议版本、database版本与password版本之间的关系

如下表:

时间: 2024-10-07 00:02:49

从一个案例窥探ORACLE的PASSWORD_VERSIONS的相关文章

通过一个案例彻底读懂10046 trace--字节级深入破解

转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/37840583 2014.7.23晚20:30 Oracle support组猫大师分享<通过一个案例彻底读懂10046 trace--字节级深入破解> 如需了解很多其它课程请登录站点http://www.jianfengedu.com/Discuz/detail/id/56[技术分享QQ交流群]  252296815 国内首创成就QTune的顶级高手之课    -->我保证.认真

Oracle Study之案例--安装Oracle内核参数配置

Oracle Study之案例--安装Oracle内核参数配置 在Linux系统下,安装Oracle之前,除了检查操作系统的硬件和软件是否满足安装需要之外,一个重点就是修改内核参数,其中最主要的是和内存相关的参数设置. 案例分析: 查看当前系统的内核参数配置: [[email protected] ~]# sysctl -p net.ipv4.ip_forward = 0 net.ipv4.conf.default.rp_filter = 1 net.ipv4.conf.default.acce

基于CAS线程安全的计算方法 java并发编程的艺术上的一个案例

package thread; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /**  * @author  changxiangxiang  * @date 2014年8月6日 下午3:25:12  * @description  * @since  sprint2  */ public class Counter {     privat

urlretrieve关于循环下载的一个案例

# -*- coding: cp936 -*- #python 27 #xiaodeng #urlretrieve关于循环下载的一个案例 import urllib def down_list(stock_list):#传入list!!! for sid in stock_list: url='http://table.finance.yahoo.com/table.csv?s='+sid fname=sid+'.csv' ''' 文件的格式是一种,属于纯文本文件 注意,for循环和url的相对

Vue一个案例引发「内容分发slot」的最全总结

今天我们继续来说说 Vue,目前一直在自学 Vue 然后也开始做一个项目实战,我一直认为在实战中去发现问题然后解决问题的学习方式是最好的,所以我在学习一些 Vue 的理论之后,就开始自己利用业余时间做了一个项目,然后通过项目中的一些案例进行总结. 今天我们来说说 Vue 中的内容分发 <slot>,首先 Vue 实现了一套内容分发的 API,这套 API 是基于当前的 Web Components 规范草案,将 <slot> 元素作为承载内分发内容的出口,内容分发是 Vue 中一个

通过一个案例分析为什么使用ThreadLocal,使用它的好处是什么

在博客园里翻过很多博客,对高手们甚是敬畏,谢谢你们教会了我许多!我也尝试贡献一点自己的学习心得,这是我的第一篇博客,纯原创,谢谢. 这里我想聊的是ThreadLocal,本地线程变量.不单独作概念上的解释了,网上太多.我以一个案例为主线一步步说明为什么我们需要用ThreadLocal?使用ThreadLocal的好处又在哪儿?案例又怎么跟随我们的思维一步步改进.具体的说明都在案例的注释中. 第一步: 第二步: 第三步: 第三步的TransactionManager工具类: 第四步: 第四步中工具

微服务开发实战(spring-cloud/spring-cloud-alibaba/dubbo),一个案例,手把手带你入门

平日里,都是看别人的文章,虽开公众号写了不少,但像样的不多.年末了,年终总结也没来得及写,为了输出点像样的东西,立刻就着手这个系列.一个键一个字母的敲,边敲边写,文章还在持续更新中,直至完整.相信通过这个系列的系统练习,能有一个大跨步的提升. 专栏简介(是什么?) 结合SpringCloud.SpringCloudAlibaba.Dubbo等开源套件,基于某商场停车业务需求,进行微服务开发实战,力争通过一个案例的实操,掌握微服务架构中常用的技能点,轻松入门. 为什么要写这个专栏(为什么?) 微服

作为一个新手的Oracle(DBA)学习笔记【转】

一.Oracle的使用 1).启动 *DQL:数据查询语言 *DML:数据操作语言 *DDL:数据定义语言 DCL:数据控制语言 TPL:事务处理语言 CCL:指针控制语言 1.登录 Win+R—cmd—>sqlplus “/as sysdba” //以sysdba用户登录,这样可以管理权限,添加用户等 Win+R—cmd—>sqlplus username/password //以指定用户名密码登录 win+R —> cmd —–> sqlplus //按照提示,输入用户名密码 

一个案例深入Python中的__new__和__init__

准备 在Python中,一切皆对象. 既然一切皆对象,那么类也是对象,我们暂且称之为 类对象.来个简单例子(本篇文章的所有案例都是运行在Python3.4中): class foo(): pass print(id(foo)) print(type(foo)) # 结果: # 46627056 # <class 'type'> 如果想深入了解一下,可以看:深刻理解Python中的元类(metaclass) 引入 最近在阅读tornado源码,发现在其源码中有很多类是这样的: class HTT