PAM机制

2023-11-20

一.PAM简介

Linux-PAM(linux可插入认证模块)是一套共享库,使本地系统管理员可以随意选择程序的认证方式. 
换句话说,不用(重新编写和)重新编译一个包含PAM功能的应用程序,就可以改变它使用的认证机制. 
这种方式下,就算升级本地认证机制,也不用修改程序. 
PAM使用配置文件/etc/pam.conf(或/etc/pam.d/下的文件),来管理对程序的认证方式.应用程序 
调用相应的配置文件,从而调用本地的认证模块.模块放置在/lib/security下,以加载动态库的形式进 
行调用(dlopen(3)). 
像我们使用su命令时,系统会提示你输入root用户的密码.这就是su命令通过调用PAM模块实现的.

二. PAM的配置文件介绍

1.PAM配置文件的格式

PAM配置文件有两种写法: 一种是写在/etc/pam.conf中.格式如下: 
ftpd auth required pam_unix.so nullok 

ftpd:表示服务名,即针对哪一个服务进行的认证配置. 
required:为模块类型.PAM有四中模块类型,分别代表不同的任务类型. 
pam_unix.so:为模块路径.即要调用模块的位置. 
nullok:为模块参数,即传递给模块的参数. 

另一种写法是,将PAM配置文件放到/etc/pam.d/目录下,使用应用程序名作为配置文件名.如: 
vsftpd,login等.配置文件的格式与pam.conf类似,只是少了最左边的服务名列.如:/etc/pam.d/cups

#%PAM-1.0
auth    required        pam_stack.so service=system-auth
account required        pam_stack.so service=system-auth

2.PAM的模块类型

Linux-PAM有四种模块类型,分别代表四种不同的任务.它们是:认证管理,账号管理,会话管理和密码 
管理.一个类型可能有多行,它们按顺序依次由PAM模块调用.

auth
	用来对用户的身份进行识别.如:提示用户输入密码,或判断用户是否为root等.
account
	对帐号的各项属性进行检查.如:是否允许登录,是否达到最大用户数,或是root用户是否允许在
这个终端登录等.

session
	这个模块用来定义用户登录前的,及用户退出后所要进行的操作.如:登录连接信息,用户数据的
打开与关闭,挂载文件系统等.

password
	使用用户信息来更新.如:修改用户密码.
<span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">PAM的功能被分为四个部分: (1) authentication(认证), (2)account</span><span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">(账号管理), (3) session (对话管理), 和 (4) password (密码管理).</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">(a) Authentication management:</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">包括 `pam_authenticate()' 来认证用户, `pam_setcred()' 来</span><span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">设置 刷新和销毁用户的 credentials.</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">(b) Account management:</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">包括 `pam_acct_mgmt()' 来检查用的账号是否还有效.可以被用来</span><span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">检查用户是否超时或账号是否过期.</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">(c) Session management:</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">包括 `pam_open_session()' 和 `pam_close_session()' 用于对话</span><span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">过程的管理. 例如: 可以用来纪录用户的连接时间. 一次telnet过程</span><span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">实际上也是一个session.</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">(d) Password management:</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">`pam_chauthtok()' 用来修该密码.</span><span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">程序通过调用 `pam_start()'和 `pam_end()' 来开始或结束一次PAM 事务.</span> <span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">`pam_get_item()' 和 `pam_set_item()' 读写有关事务的信息.</span><span style="word-wrap: break-word; font-family: Simsun; font-size: 14px; line-height: 16.78333282470703px; white-space: normal; background-color: rgb(247, 247, 247);">可以用`pam_strerror()'来取得错误信息.</span> 

3.PAM的控制标记

PAM使用控制标记来处理和判断各个模块的返回值.

required
	这个标记表示需要模块返回一个成功值.如果返回失败,则继续进行同类型的下一个操作,当
所有此类型的模块都执行完后.才返回失败值.

requisite
	与required相似,但是如果这个模块返回失败,则立刻向应用程序返回失败,表示此类型失败.
不再进行同类型后面的操作.

sufficient
	如果此模块返回成功,则直接向应用程序返回成功,表示此类型成功.不再进行同类型后面
的操作.如果失败,也不会影响这个类型的返回值.

optional
	使用这个标记的模块,将不进行成功与否的返回.一般返回一个PAM_IGNORE(忽略).

4.模块路径

模块路径.即要调用模块的位置. 一般保存在/lib/security/下,如: pam_unix.so 
同一个模块,可以出现在不同的类型中.它在不同的类型中所执行的操作都不相同.这是由于每个模块 
针对不同的模块类型,编制了不同的执行函数.

5.模块参数

模块参数,即传递给模块的参数.参数可以有多个,之间用空格分隔开,如:

password   required   pam_unix.so nullok obscure min=4 max=8 md5

三.编写PAM配置文件

1.PAM模块介绍

pam_unix.so模块: 
auth类型: 提示用户输入密码,并与/etc/shadow文件相比对.匹配返回0(PAM_SUCCESS). 
account类型: 检查用户的账号信息(包括是否过期等).帐号可用时,返回0. 
password类型: 修改用户的密码. 将用户输入的密码,作为用户的新密码更新shadow文件

pam_cracklib.so模块: 
password类型: 这个模块可以插入到一个程序的密码栈中,用于检查密码的强度. 
这个模块的动作是提示用户输入密码,并与系统中的字典进行比对,检查其强度. 

pam_loginuid.so模块: 
session类型:用来设置已通过认证的进程的uid.以使程序通过正常的审核(audit). 

pam_securetty.so模块: 
auth类型: 如果用户要以root登录时,则登录的tty必须在在/etc/securetty中法之前. 

pam_rootok.so模块: 
auth类型: pam_rootok模块用来认证用户id是否为0.为0返回”PAM_SUCCESS”. 

pam_console.so模块: 
session类型: 当用户登录到终端时,改变终端文件文件的权限.在用户登出后,再将它们修改回来. 

pam_permit.so模块: 
auth,account,password,session类型: pam_permit模块任何时候都返回成功. 

pam_env.so模块 : 
auth类型: pam_env允许设置环境变量.默认下,若没有指定文件,将依据 
/etc/security/pam_env.conf进行环境变量的设置. 

pam_xauth.so模块: 
session类型: pam_xauth用来在用户之间转发xauth-key. 
如果不进行pam_xauth,当用户调用su成为另一个用户时,这个用户将不可以再访问原来用户的X显示, 
因为新用户没有访问显示的key.pam_xauth解决了当会话建立时,从原始用户到目标用户转发key和用户 
退出时销毁key的问题.

实验:
注销/etc/pam.d/su中的"session    optional     /lib/security/$ISA/pam_xauth.so"行
在桌面终端执行su切换到另一个用户时,执行xterm会报错,提示无法访问DISPLAY.
删除注释后,再使用su切换到另一个用户时,执行xterm,会正常打开一个xterm终端窗口.


pam_stack.so模块: 
auth,account,password,session: pam_stack可以调用另一个服务.也就是多个服务可以包含到一个 
设置中.当需要修改时,只修改一个文件就可以了. 

pam_warn.so模块: 
auth,account,password,session: pam_warn用来记录服务,终端,用户,远程用户和远程主机的信息 
到系统日志.模块总是返回PAM_IGNORE,意指不希望影响到认证处理.

2.编写PAM配置文件

以root身份执行: # vi /etc/pam.d/pamtest

#提示用户输入密码
auth     required   pam_unix.so
# 验证用户账号是否可用
account  required   pam_unix.so
# 向系统日志输出一条信息
account  required   pam_warn.so

四.基于PAM机制的应用程序

1.编写C源码

#include <security pam_appl="" h="" style="word-wrap: break-word;">
#include <security pam_misc="" h="" style="word-wrap: break-word;">
#include <security pam_modules="" h="" style="word-wrap: break-word;">
#include <stdio h="" style="word-wrap: break-word;">
/* 文件pamtest.c
此程序从命令行接收一个用户名作为参数,然后对这个用户名进行auth和account验证.
*/
// 定义一个pam_conv结构,用于与pam通信
       static struct pam_conv conv = {
           misc_conv,
           NULL
       };
// 主函数
       int main(int argc, char *argv[])
       {
           pam_handle_t *pamh=NULL;
           int retval;
           const char *user="nobody";
	   const char *s1=NULL;

           if(argc == 2)
               user = argv[1];
	   else
	       exit(1);

           if(argc > 2) {
               fprintf(stderr, "Usage: pamtest0 [username]/n");
               exit(1);
           }
	   printf("user: %s/n",user);
	   retval = 0;

//调用pamtest配置文件
           retval = pam_start("pamtest", user, &conv, &pamh);

           if (retval == PAM_SUCCESS)

//进行auth类型认证
               retval = pam_authenticate(pamh, 0);    /* is user really user? */
	   else {
//如果认证出错,pam_strerror将输出错误信息.
		   printf("pam_authenticate(): %d/n",retval);
		   s1=pam_strerror( pamh, retval);
		   printf("%s/n",s1);
		}
           if (retval == PAM_SUCCESS)

//进行account类型认证
               retval = pam_acct_mgmt(pamh, 0);       /* permitted access? */
	   else {
		   printf("pam_acct_mgmt() : %d/n",retval);
		   s1=pam_strerror( pamh, retval);
		   printf("%s/n",s1);
		}
           /* This is where we have been authorized or not. */

           if (retval == PAM_SUCCESS) {
               fprintf(stdout, "Authenticated/n");
           } else {
               fprintf(stdout, "Not Authenticated/n");
           }

           if (pam_end(pamh,retval) != PAM_SUCCESS) {     /* close Linux-PAM */
               pamh = NULL;
               fprintf(stderr, "pamtest0: failed to release authenticator/n");
               exit(1);
           }

           return ( retval == PAM_SUCCESS ? 0:1 );       /* indicate success */
       }
//END
</stdio></security></security></security>

2.编译

$ cc -o pamtest pamtest.c -lpam -lpam_misc -ldl

3.编写PAM配置文件

以root身份执行: vi /etc/pam.d/pamtest

auth  required  /lib/security/pam_unix.so
account required /lib/security/pam_unix.so

4. 修改可执行程序权限

由于pam_unix.so需要访问/etc/shadow和/etc/passwd文件,所以要给pamtest文件附上SUID权限.

# chown root.root pamtest
# chmod 111 pamtest
# ls pamtest
# ls pamtest -hl
---s--x--x 1 root root 12K 2007-07-16 01:52 pamtest

5.执行

pamtest程序通过pam_unix.so,先对用户的密码进行验证,然后对用户的账号信息进行验证. 
以普通用户身份执行,输入错误的maj密码时.

maj@m2-u:01:52:09/var/tmp$ ./pamtest maj
user: maj
Password: 
pam_acct_mgmt() : 7
Authentication failure
Not Authenticated

输入正确的密码时

maj@m2-u:01:54:44/var/tmp$ ./pamtest maj
user: maj
Password: 
Authenticated

输入错误的root密码时

maj@m2-u:01:58:37/var/tmp$ ./pamtest root
user: root
Password: 
pam_acct_mgmt() : 7
Authentication failure
Not Authenticated
maj@m2-u:01:59:15/var/tmp$ 

输入正确的root密码时

maj@m2-u:01:54:50/var/tmp$ ./pamtest root
user: root
Password: 
Authenticated
maj@m2-u:01:58:37/var/tmp$ 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PAM机制 的相关文章

  • Linux、ARM:为什么仅当启动时存在 I2C GPIO 扩展器时才创建 gpiochip

    在 imx6sx 硬件平台 NXP 嵌入式 ARM 上使用 Linux 3 14 52 问题是设备树中指定的 PCF8575 I2C GPIO 扩展器不会实例化为 sys class gpio 结构中的设备 除非它们在内核启动期间存在 这些
  • 如何从 Linux 的 shell 中删除所有以 ._ 开头的文件?

    确实如标题所示 我已将许多文件从 Mac 复制到 Raspberry Pi 这导致了许多以前缀开头的多余文件 我想删除以以下开头的文件夹中的每个文件 我该怎么做 尝试类似的方法 cd path to directory rm rf 或者 如
  • 在 shell 脚本中查找和替换

    是否可以使用 shell 在文件中搜索然后替换值 当我安装服务时 我希望能够在配置文件中搜索变量 然后在该值中替换 插入我自己的设置 当然 您可以使用 sed 或 awk 来完成此操作 sed 示例 sed i s Andrew James
  • 进程名称长度的最大允许限制是多少?

    进程名称允许的最大长度是多少 我正在读取进程名称 proc pid stat文件 我想知道我需要的最大缓冲区 我很确定有一个可配置的限制 但就是找不到它在哪里 根据man 2 prctl http man7 org linux man pa
  • 如何确保 numpy BLAS 库可用作动态加载库?

    The theano安装文档 http www deeplearning net software theano install html troubleshooting make sure you have a blas library指
  • 无法仅在控制台中启动 androidstudio

    你好 我的问题是下一个 我下载了Android Studio如果我去 路径 android studio bin 我执行studio sh 我收到以下错误 No JDK found Please validate either STUDIO
  • 如何查明 Ubuntu 上安装了哪个版本的 GTK+?

    我需要确定 Ubuntu 上安装了哪个版本的 GTK 男人似乎不帮忙 这个建议 https stackoverflow com a 126145 会告诉您安装了哪个 2 0 的次要版本 不同的主要版本将具有不同的包名称 因为它们可以在系统上
  • Linux 中热插拔设备时检测设备是否存在

    我正在运行 SPIcode http lxr free electrons com source drivers spi spi omap2 mcspi c在熊猫板上 我想知道其中的哪个功能code http lxr free electr
  • 为 Qt 应用程序创建 Linux 安装

    我刚刚用 Qt Creator 制作了一个很棒的程序 我对自己很满意 如何将其从台式机移至笔记本电脑 那么 最好的方法是安装程序 对吗 对于 Ubuntu 这是一个 Debian 软件包 对吗 我怎么做 有人这样做过吗 他们可以分享 QT
  • 如何不断刷新屏幕并实时更新[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想在linux上写一个C程序 不断刷新屏幕并实时更新 例如类似于top终端中的命令 谁能指出我正确的方向 为了保持它跨终端类型的可移
  • 如何在Python中独立于语言安装(linux)获取用户桌面路径

    我找到了 如何找到用户桌面的路径 的几个问题和答案 但在我看来它们都已失效 至少我找到的那些 原因是 如果用户安装的 Linux 不是英语 他或她的桌面很可能位于除 Desktop 例如 对于瑞典语 我相信它是在 Skrivbord 谁知道
  • Bash 方法的返回值总是模 256

    我有一个 bash 脚本方法 它返回输入值 然而 返回值始终是模 256 的值 我用 google 搜索了一段时间 发现this http www tldp org LDP abs html exitcodes html文章说它总是以 25
  • sleep 0 有特殊含义吗?

    我看到很多用法sleep 0在我的一个客户项目中 代码看起来像这样 while true sleep 0 end 阅读一些像这样的答案this https stackoverflow com questions 3727420 signif
  • C 程序从连接到系统的 USB 设备读取数据

    我正在尝试从连接到系统 USB 端口的 USB 设备 例如随身碟 获取数据 在这里 我可以打开设备文件并读取一些随机原始数据 但我想获取像 minicom teraterm 这样的数据 请让我知道我可以使用哪些方法和库来成功完成此操作以及如
  • 无需 cron 在后台发送邮件

    我想知道是否有一种方法可以运行 PHP 循环 以便在后台向订阅者发送几百封电子邮件 我的目标是格式化新闻通讯 单击发送 然后关闭浏览器或更改页面 当然 发送电子邮件的实际过程将在后台运行 不会因浏览器关闭而中断 我知道这可以通过 cron
  • 劫持系统调用

    我正在编写一个内核模块 我需要劫持 包装一些系统调用 我正在暴力破解 sys call table 地址 并使用 cr0 来禁用 启用页面保护 到目前为止一切顺利 一旦完成 我将公开整个代码 因此如果有人愿意 我可以更新这个问题 无论如何
  • 如何使用 sed 仅删除双空行?

    我找到了这个问题和答案 https stackoverflow com questions 4651591 howto use sed to remove only triple empty lines关于如何删除三重空行 但是 我只需要对
  • GCC 和 ld 找不到导出的符号...但它们在那里

    我有一个 C 库和一个 C 应用程序 尝试使用从该库导出的函数和类 该库构建良好 应用程序可以编译 但无法链接 我得到的错误遵循以下形式 app source file cpp text 0x2fdb 对 lib namespace Get
  • 如何制作和应用SVN补丁?

    我想制作一个SVN类型的补丁文件httpd conf这样我就可以轻松地将其应用到其他主机上 If I do cd root diff Naur etc httpd conf httpd conf original etc httpd con
  • 如何更改 Ubuntu 14.04 上的 php-cli 版本?

    我是 Linux 新手 在篡改时破坏了一些 php 设置 如果我执行一个包含以下内容的 php 脚本 phpinfo 它显示 php 版本为 5 6 但通过命令行 如果我运行php v它返回 7 0 版本 我想让两个版本匹配 我怎样才能修复

随机推荐

  • java 二阶段提交,二阶段提交协议(Two Phase Commitment Protocol)

    一 典型的分布式事务实例 跨行转账问题是一个典型的分布式事务 用户A向B的一个转账1000 要进行A的余额 1000 B的余额 1000 显然必须保证这两个操作的事务性 类似的还有 电商系统中 当有用户下单后 除了在订单表插入记 还要在商品
  • mysql数据库常用sql语句

    数据库可以用图形化工具来实现一系列操作 这里涉及一些cmd命令行 首先要配置好环境变量可以全局操作命令 不然只能在mysql的安装目录下进行操作 这里不再叙述 1 进入数据库 mysql u root p 默认用户名为root 这个与mys
  • Flutter 中的单元测试:从工作流基础到复杂场景

    对 Flutter 的兴趣空前高涨 而且早就应该出现了 Google 的开源 SDK 与 Android iOS macOS Web Windows 和 Linux 兼容 单个 Flutter 代码库支持所有这些 单元测试有助于交付一致且可
  • 3种方法更改Linux系统的主机名(hostname)

    3种方法更改Linux系统的主机名 hostname
  • type-aliases-package的作用

    mapper xml文件中resultType或者parameterType会使用JavaBean作为返回结果或者参数需要使用完全限定名来指定引用 例如
  • undefined reference to ceil 链接错误

    undefined reference to ceil 链接错误 原因今天编译一个C文件 输入下面的代码后 GOP12 c文件代码大致为 include
  • 森林的先序和中序遍历

    森林的先序和中序遍历 先序遍历 中序遍历 最靠谱的方法 先序遍历 中序遍历 最靠谱的方法 把森林转为二叉树 左孩子 右兄弟的那种 然后对二叉树进行先序或中序遍历即得正确结果
  • 机器ubuntu20.04和ubuntu16.04在局域网下ros通信

    多台机器ros局域网通信 试过在ubuntu16 04的机器人和ubuntu20 04下安装不同版本ros通信 测试成功 首先保证两台机器在同一个局域网内 可以相互ping通 1 查看ip地址 ifconfig 2 ssh远程登录机器人计算
  • Qt界面制作简单教程,调用python代码

    利用Qt5design或Qt5Creator制作界面的布局 包括设置按钮的个数 布局和大小等 注意记得为每个按钮添加槽函数 保存生成 ui文件 利用pyuic5 xxx ui gt xxx py或pyuic5 xxx ui o xxx py
  • 最全的雅思8000词汇pdf_助力9分

    词汇是雅思学习的基础 对此我们特别设立 9分词汇 小栏目 专门分享词汇相关干货 包括但不限于 高频词解析 场景词汇总结 熟词辟义 同义替换等等 如果你还有其他有关词汇想要学习了解的 欢迎给我们留言 一定及时为大家补充 雅思听力part 1
  • html点击收缩展开菜单栏,jquery实现点击向下展开菜单项(伸缩导航)效果

    本文实例讲述了jquery实现点击向下展开菜单项 伸缩导航 效果 分享给大家供大家参考 具体如下 这里演示基于jquery打造的向下展开的多级导航条效果 纵向垂直排列 风格非常的简洁 鼠标点击时候展开菜单的二级项 再次点击的时候又向上合拢
  • Spring事务传播属性

    参考文献 Spring事务传播属性和隔离级别 https www cnblogs com eunice sun p 11024584 html spring事务传播机制总结 https blog csdn net m18330808841
  • GBA编程和汉化常用软件汇总

    内容来自GBA吧中的痴狂小黑 本人只是做个汇总和搬运 1 简易图片导入导出套装 PicSimpleImEx AutoPicRock Ver1 0 这两个软件是用C 写的 想要用 先装dotNetFx40 Full x86 x64 exe 然
  • 算法问题实战策略

    算法问题实战策略 基本信息作者 韩 具宗万 译者 崔盛一出版社 人民邮电出版社ISBN 9787115384621上架时间 2015 2 4出版日期 2015 年3月开本 16开页码 738版次 1 1 内容简介 算法问题实战策略 本书收录
  • 手动搭建torch2.0环境

    一 下载相关whl 1 从Previous PyTorch Versions PyTorch检查相互版本是否兼容 否则会出现无法使用cuda的问题 2 从https download pytorch org whl torch stable
  • 阶乘质因子分解(唯一分解定理)

    阶乘质因子分解 题目描述 对N 进行质因子分解 输入输出格式 输入格式 输入数据仅有一行包含一个正整数N N lt 10000 输出格式 输出数据包含若干行 每行两个正整数p a 中间用一个空格隔开 表示N 包含a个质因子p 要求按p的值从
  • Python JS逆向篇(一)

    Python JS逆向篇 一 效果实现 思路 最后一步 逆向 p a HmacSHA256 t s a state commonStore cupid sign key JS实现 py实现 先苦后甜 逆向主题 51job请求头headers
  • 【NodeJS】Express框架快速入门

    简介 作为前端开发 Nodejs已经成了很多公司对我们这一岗位的硬性要求 而 Express 框架则是其中知名度最高 也是最受欢迎的Nodejs开发框架 它帮助我们封装了Nodejs底层的API 屏蔽了大量的繁琐的细节 让我们只需要关注业务
  • Mybatis框架解析

    一 Mybatis框架简介 MyBatis框架是一个开源的数据持久层框架 它的内部封装了通过JDBC访问数据库的操作 支持普通的SQL查询 存储过程和高级映射 几乎消除了所有的JDBC代码和参数的手工设置以及结果集的检索 MyBatis作为
  • PAM机制

    一 PAM简介 Linux PAM linux可插入认证模块 是一套共享库 使本地系统管理员可以随意选择程序的认证方式 换句话说 不用 重新编写和 重新编译一个包含PAM功能的应用程序 就可以改变它使用的认证机制 这种方式下 就算升级本地认