Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成。SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。SMB协议是客户机/服务器型协议,客户机通过该协议可以访问服务器上的共享文件系统、打印机及其他资源。通过设置“NetBIOS over TCP/IP”使得Samba不但能与局域网络主机分享资源,还能与全世界的电脑分享资源。
我的出发点是想配置samba使用openldap进行认证,我想大部分人听到这都会说,samba很简单的,和openldap结合很容易的,但是我却发现,网上90%以上的文章都是将两者部署到一台Linux Server上,无论是Unbutu,CentOS还是Fedora,所以当我看到一个将samba和openldap部署在两台Unbutu上遇到问题的帖子(2012年的)竟然无一人回答时,突然觉得有时候人云亦云未必是对的,在你对一个事情彻底了解之前你无法也不应该像别人一样给它贴上一个简单的标签,做学问还是要认真的,以上仅是个人见解,下面开始部署独立的samba,然后在和openldap整合。
openldap的部署在之前有一篇博文记录,这里的openldap环境也建立在上次的基础上,仅仅需要准备一台CentOS 6.5用来部署samba。
1、准备工作
1
2
3
4
|
/etc/init
.d
/iptables
stop
setenforce 0
echo
"192.168.49.135 samba.contoso.com samba"
>>
/etc/hosts
#samba主机记录
echo
"192.168.49.138 ldapsrv01.contoso.com ldapsrv01"
>>
/etc/hosts
#openldap server记录
|
[root@samba ~]# tail -2 /etc/hosts
192.168.49.135 samba.contoso.com samba
192.168.49.138 ldapsrv01.contoso.com ldapsrv01
[root@samba ~]# ping ldapsrv01.contoso.com -c 1
PING ldapsrv01.contoso.com (192.168.49.138) 56(84) bytes of data.
64 bytes from ldapsrv01.contoso.com (192.168.49.138): icmp_seq=1 ttl=64 time=1.73 ms
--- ldapsrv01.contoso.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 2ms
rtt min/avg/max/mdev = 1.737/1.737/1.737/0.000 ms
2、启用system-wide并使用LDAP认证
为了使samba server能够使用openldap认证,必须要在/etc/nsswith.conf文件中配置使用ldap,使用下面的命令即可:
1
|
authconfig --enableldap --update
|
[root@samba ~]# egrep -v "#|^$" /etc/nsswitch.conf
passwd: files ldap
shadow: files ldap
group: files ldap
hosts: files dns
bootparams: nisplus [NOTFOUND=return] files
ethers: files
netmasks: files
networks: files
protocols: files
rpc: files
services: files
netgroup: files ldap
publickey: nisplus
automount: files ldap
aliases: files nisplus
实际上,该条命令的目的就是在/etc/nsswith.conf中的
passwd, shadow, group, netgroup和automount条目增加ldap选项,如果不想使用上面的命令,手工进行添加也是可以的,这个可以参照之前openldap client配置中的方法。
3、安装samba软件包
1
|
yum
install
samba samba-common
|
注意:这里安装的是samba 3.6.23,然后和openldap 2.4.40进行整合,使用yum安装的时候不要安装成samba4的版本了。
[root@samba ~]# yum list all|grep samba
samba.x86_64 3.6.23-36.el6_8 @updates
samba-common.x86_64 3.6.23-36.el6_8 @updates
samba-winbind.x86_64 3.6.23-36.el6_8 @updates
samba-winbind-clients.x86_64 3.6.23-36.el6_8 @updates
pcp-pmda-samba.x86_64 3.10.9-6.el6 base
samba-client.x86_64 3.6.23-36.el6_8 updates
samba-common.i686 3.6.23-36.el6_8 updates
samba-doc.x86_64 3.6.23-36.el6_8 updates
samba-domainjoin-gui.x86_64 3.6.23-36.el6_8 updates
samba-glusterfs.x86_64 3.6.23-36.el6_8 updates
samba-swat.x86_64 3.6.23-36.el6_8 updates
samba-winbind-clients.i686 3.6.23-36.el6_8 updates
samba-winbind-devel.i686 3.6.23-36.el6_8 updates
samba-winbind-devel.x86_64 3.6.23-36.el6_8 updates
samba-winbind-krb5-locator.x86_64 3.6.23-36.el6_8 updates
samba4.x86_64 4.2.10-7.el6_8 updates
samba4-client.x86_64 4.2.10-7.el6_8 updates
samba4-common.x86_64 4.2.10-7.el6_8 updates
samba4-dc.x86_64 4.2.10-7.el6_8 updates
samba4-dc-libs.x86_64 4.2.10-7.el6_8 updates
samba4-devel.x86_64 4.2.10-7.el6_8 updates
samba4-libs.x86_64 4.2.10-7.el6_8 updates
samba4-pidl.x86_64 4.2.10-7.el6_8 updates
samba4-python.x86_64 4.2.10-7.el6_8 updates
samba4-test.x86_64 4.2.10-7.el6_8 updates
samba4-winbind.x86_64 4.2.10-7.el6_8 updates
samba4-winbind-clients.x86_64 4.2.10-7.el6_8 updates
samba4-winbind-krb5-locator.x86_64 4.2.10-7.el6_8 updates
sblim-cmpi-samba.i686 1.0-1.el6 base
sblim-cmpi-samba.x86_64 1.0-1.el6 base
sblim-cmpi-samba-devel.i686 1.0-1.el6 base
sblim-cmpi-samba-devel.x86_64 1.0-1.el6 base
sblim-cmpi-samba-test.x86_64 1.0-1.el6 base
4、拷贝samba schema到openldap server(此步骤需要到openldap server上操作)
说明:因为这些操作需要在配置smb.conf文件之前操作,所以并未将samba服务器上的操作和openldap server上的操作分开来,但是如果是需要在openldap server上操作,我都会注明的。
默认情况下,openldap server并不会读取samba的配置,如果想让openldap server能理解samba,那么就需要添加samba的ldap schema,ldap schema就是在/etc/openldap/slapd.d/下面的schema,默认情况下是没有关于samba的schema,所以我们需要从samba服务器上拷贝到openldap服务器端。
[root@samba ~]# rpm -ql samba
....
/usr/share/doc/samba-3.6.23
/usr/share/doc/samba-3.6.23/LDAP
/usr/share/doc/samba-3.6.23/LDAP/README
/usr/share/doc/samba-3.6.23/LDAP/convertSambaAccount
/usr/share/doc/samba-3.6.23/LDAP/get_next_oid
/usr/share/doc/samba-3.6.23/LDAP/ol-schema-migrate.pl
/usr/share/doc/samba-3.6.23/LDAP/samba-nds.schema
/usr/share/doc/samba-3.6.23/LDAP/samba-schema-FDS.ldif
/usr/share/doc/samba-3.6.23/LDAP/samba-schema-netscapeds5.x.README
/usr/share/doc/samba-3.6.23/LDAP/samba-schema.IBMSecureWay
/usr/share/doc/samba-3.6.23/LDAP/samba.ldif
/usr/share/doc/samba-3.6.23/LDAP/samba.schema
/usr/share/doc/samba-3.6.23/LDAP/samba.schema.at.IBM-DS
/usr/share/doc/samba-3.6.23/LDAP/samba.schema.oc.IBM-DS
...
这是samba安装后生成的关于LDAP文件(其他的大部分被我省去),里面有schema字样的就是samba的ldap schema,当然有些是IBM的特殊文件(因为IBM有自己的一套ldap),而我们需要的就是samba.ldif这个文件。
1
2
|
scp
/usr/share/doc/samba-3
.6.23
/LDAP/samba
.ldif root@ldapsrv01:
/etc/openldap/slapd
.d
/cn
\=config
/cn
\=schema
chown
-R ldap:ldap
/etc/openldap/slapd
.d
|
然后编辑/etc/openldap/slapd.conf文件,添加一行:
include /etc/openldap/schema/samba.schema
修改之后的slapd.conf文件中,应该包含如下内容:
include /etc/openldap/schema/corba.schema
include /etc/openldap/schema/core.schema
include /etc/openldap/schema/cosine.schema
include /etc/openldap/schema/duaconf.schema
include /etc/openldap/schema/dyngroup.schema
include /etc/openldap/schema/inetorgperson.schema
include /etc/openldap/schema/java.schema
include /etc/openldap/schema/misc.schema
include /etc/openldap/schema/nis.schema
include /etc/openldap/schema/openldap.schema
include /etc/openldap/schema/ppolicy.schema
include /etc/openldap/schema/collective.schema
include /etc/openldap/schema/samba.schema
5、编辑samba.ldif文件(此步骤需要到openldap server上操作)
在openldap server上,/etc/openldap/slapd.d/cn=config/cn=schema/下的文件都以一定的方式命名(如下所示),如cn={x}core.ldif等,x的值需要设置为当前目录下所有文件的{}中的最大值加1,默认情况下安装完openldap之后,{}中的最大值是11,也即cn={11}collective.ldif,所以samba.ldif就需要改名为cn={12}samba.ldif。
[root@ldapsrv01 ~]# ll /etc/openldap/slapd.d/cn\=config/cn\=schema
total 76
-rw-------. 1 ldap ldap 1283 Sep 8 12:46 cn={0}corba.ldif
-rw-------. 1 ldap ldap 3625 Sep 8 12:46 cn={10}ppolicy.ldif
-rw-------. 1 ldap ldap 1523 Sep 8 12:46 cn={11}collective.ldif
-rw-------. 1 ldap ldap 15546 Sep 8 12:46 cn={1}core.ldif
-rw-------. 1 ldap ldap 11363 Sep 8 12:46 cn={2}cosine.ldif
-rw-------. 1 ldap ldap 4489 Sep 8 12:46 cn={3}duaconf.ldif
-rw-------. 1 ldap ldap 1693 Sep 8 12:46 cn={4}dyngroup.ldif
-rw-------. 1 ldap ldap 2857 Sep 8 12:46 cn={5}inetorgperson.ldif
-rw-------. 1 ldap ldap 2589 Sep 8 12:46 cn={6}java.ldif
-rw-------. 1 ldap ldap 1519 Sep 8 12:46 cn={7}misc.ldif
-rw-------. 1 ldap ldap 6495 Sep 8 12:46 cn={8}nis.ldif
-rw-------. 1 ldap ldap 1323 Sep 8 12:46 cn={9}openldap.ldif
下面对samba.ldif进行改名(注意在Linux中“=”和“{}”需要转义)
[root@ldapsrv01 ~]# ll /etc/openldap/slapd.d/cn\=config/cn\=schema/sam*
-rw-r--r-- 1 root root 14440 Sep 13 11:02 /etc/openldap/slapd.d/cn=config/cn=schema/samba.ldif
[root@ldapsrv01 ~]# cd /etc/openldap/slapd.d/cn\=config/cn\=schema
[root@ldapsrv01 cn=schema]# mv samba.ldif cn\=\{12\}samba.ldif
[root@ldapsrv01 cn=schema]# ll
total 92
-rw-------. 1 ldap ldap 1283 Sep 8 12:46 cn={0}corba.ldif
-rw-------. 1 ldap ldap 3625 Sep 8 12:46 cn={10}ppolicy.ldif
-rw-------. 1 ldap ldap 1523 Sep 8 12:46 cn={11}collective.ldif
-rw-r--r-- 1 root root 14440 Sep 13 11:02 cn={12}samba.ldif
-rw-------. 1 ldap ldap 15546 Sep 8 12:46 cn={1}core.ldif
-rw-------. 1 ldap ldap 11363 Sep 8 12:46 cn={2}cosine.ldif
-rw-------. 1 ldap ldap 4489 Sep 8 12:46 cn={3}duaconf.ldif
-rw-------. 1 ldap ldap 1693 Sep 8 12:46 cn={4}dyngroup.ldif
-rw-------. 1 ldap ldap 2857 Sep 8 12:46 cn={5}inetorgperson.ldif
-rw-------. 1 ldap ldap 2589 Sep 8 12:46 cn={6}java.ldif
-rw-------. 1 ldap ldap 1519 Sep 8 12:46 cn={7}misc.ldif
-rw-------. 1 ldap ldap 6495 Sep 8 12:46 cn={8}nis.ldif
-rw-------. 1 ldap ldap 1323 Sep 8 12:46 cn={9}openldap.ldif
然后我们需要编辑一下该文件
[root@ldapsrv01 cn=schema]# head -3 cn\=\{12\}samba.ldif
dn: cn=samba,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: samba
#编辑前的源文件
[root@ldapsrv01 cn=schema]# vi cn\=\{12\}samba.ldif
[root@ldapsrv01 cn=schema]# head -3 cn\=\{12\}samba.ldif
dn: cn={12}samba.ldif
objectClass: olcSchemaConfig
cn: cn={12}samba.ldif
#编辑后的新文件
最后,重启slapd服务
1
|
/etc/init
.d
/slapd
restart
|
如果要检查samba schema是否加载,可以使用如下命令:
ldapsearch -x -b "dc=contoso,dc=com"
# extended LDIF
#
# LDAPv3
# base <dc=contoso,dc=com> with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# contoso.com
dn: dc=contoso,dc=com
objectClass: organization
objectClass: dcObject
dc: contoso
o: contoso
# People, contoso.com
dn: ou=People,dc=contoso,dc=com
objectClass: organizationalUnit
ou: People
# group, contoso.com
dn: ou=group,dc=contoso,dc=com
objectClass: organizationalUnit
ou: group
# machines, contoso.com
dn: ou=machines,dc=contoso,dc=com
objectClass: organizationalUnit
ou: machines
# sudoers, group, contoso.com
dn: cn=sudoers,ou=group,dc=contoso,dc=com
objectClass: posixGroup
description: sudoers
gidNumber: 10000
cn: sudoers
# charles lv, People, contoso.com
dn: cn=charles lv,ou=People,dc=contoso,dc=com
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
homeDirectory: /home/charleslv
loginShell: /bin/bash
uid: charleslv
cn: charles lv
uidNumber: 10000
gidNumber: 10000
userPassword:: e1NTSEF9YW8wUkhDdElFYTh0Yy9RU3Q0QitXdDY4ckJsU2VGQm8=
description: charles lv
sn: lv
givenName: charles
initials: charles lv
# eric li, People, contoso.com
dn: cn=eric li,ou=People,dc=contoso,dc=com
objectClass: posixAccount
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
homeDirectory: /home/ericli
loginShell: /bin/bash
uid: ericli
cn: eric li
uidNumber: 10001
gidNumber: 10000
userPassword:: e1NTSEF9eE00RFB0VkhmM2FGQnRpRUJUSTdHSnZ3S0kxdUxsSkU=
description: eric li
sn: li
givenName: eric
initials: eric li
# developers, contoso.com
dn: ou=developers,dc=contoso,dc=com
ou: developers
objectClass: organizationalUnit
objectClass: top
# app, developers, contoso.com
dn: ou=app,ou=developers,dc=contoso,dc=com
ou: app
objectClass: organizationalUnit
objectClass: top
# web, developers, contoso.com
dn: ou=web,ou=developers,dc=contoso,dc=com
ou: web
objectClass: organizationalUnit
objectClass: top
# java, developers, contoso.com
dn: ou=java,ou=developers,dc=contoso,dc=com
ou: java
objectClass: organizationalUnit
objectClass: top
# bryanz, sudoers, group, contoso.com
dn: cn=bryanz,cn=sudoers,ou=group,dc=contoso,dc=com
givenName: bryan
sn: zhao
uid: bryanz
userPassword:: e01ENX00UXJjT1VtNldhdStWdUJYOGcrSVBnPT0=
uidNumber: 1000
gidNumber: 10000
homeDirectory: /home/bryanz
loginShell: /bin/sh
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: top
cn: bryanz
# zhangs, People, contoso.com
dn: uid=zhangs,ou=People,dc=contoso,dc=com
objectClass: posixAccount
objectClass: top
objectClass: inetOrgPerson
gidNumber: 10000
givenName: zhang
sn: san
displayName: zhang san
uid: zhangs
homeDirectory: /home/zhangs
loginShell: /bin/bash
cn: zhang san
uidNumber: 47180
userPassword:: e1NTSEF9Nmk2cm1wbXpyK3JzVEwyZk0wanR6d2tKOFNWMk9FdEs=
# SAMBA, contoso.com
dn: sambaDomainName=SAMBA,dc=contoso,dc=com
sambaDomainName: SAMBA
sambaSID: S-1-5-21-3657554500-457428447-597312458
sambaAlgorithmicRidBase: 1000
objectClass: sambaDomain
sambaNextUserRid: 1000
sambaMinPwdLength: 5
sambaPwdHistoryLength: 0
sambaLogonToChgPwd: 0
sambaMaxPwdAge: -1
sambaMinPwdAge: 0
sambaLockoutDuration: 30
sambaLockoutObservationWindow: 30
sambaLockoutThreshold: 0
sambaForceLogoff: -1
sambaRefuseMachinePwdChange: 0
# search result
search: 2
result: 0 Success
# numResponses: 15
# numEntries: 14
蓝色部分说明samba的schema已经成功加载并已生效。
6、编辑samba的配置文件smb.conf
1
2
|
cp
/etc/samba/smb
.conf
/etc/samba/smb
.conf.bak$(
date
+%F)
vi
/etc/samba/smb
.conf
|
[root@samba ~]# diff /etc/samba/smb.conf.bak2016-09-12 /etc/samba/smb.conf
101,102c101,102
< security = user
< passdb backend = tdbsam
---
> #security = user
> #passdb backend = tdbsam
103a104,108
> security = user
> passdb backend = ldapsam:ldap://ldapsrv01.contoso.com
> ldap suffix = dc=contoso,dc=com
> ldap admin dn = cn=admin,dc=contoso,dc=com
> ldap ssl = no
#只是把原来的security和passdb backend注释掉,然后添加了ldap的配置。
security = user
passdb backend = ldapsam:ldap://ldapsrv01.contoso.com
ldap suffix = dc=contoso,dc=com
ldap admin dn = cn=admin,dc=contoso,dc=com
ldap ssl = no
注意:ldap admin dn是可选项,如果openldap可以进行匿名访问的话,这里可以不指定admin dn。但是,如果这里指定了admin dn,那就需要使用smbpasswd -W命令指定admin dn的密码并将它写入到secrets.tdb中。如果之前openldap server上并没有创建samba域,也会自动创建一个samba域。
[root@samba ~]# smbpasswd -w 123456
Setting stored password for "cn=admin,dc=contoso,dc=com" in secrets.tdb
[root@samba ~]# service smb restart
Shutting down SMB services: [ OK ]
Starting SMB services: [ OK ]
重启完smb服务后,执行“net getlocalsid”命令,将于看到类似如下的输出:
[root@samba ~]# net getlocalsid
SID for domain SAMBA is: S-1-5-21-3657554500-457428447-597312458
如果你是手工创建的samba域,这里就会返回samba域的信息,如果是自动创建,就会返回类似上面的信息。这也就说明samba domain已经创建成功。
补充:如果执行net getlocalsid命令,返回“Failed to issue the StartTLS instruction: Connect error”错误代码,则在/etc/samba/smb.conf中添加“ldap ssl = no”,然后重启smb服务即可。
因为之前在部署openldap后,我也部署了LAM,所以可以到LAM上看一下,是否有samba域的相关信息。
登录Ldap Account Manager,然后切换到Samba域,可以看到下面已经多了一个SAMBA的域,可以对照一下Domain SID正是上面通过net getlocalsid返回的值。
打开该域的配置,发现很多信息都是默认或者未配置的,我们也可以在这里修改或重置某些设定。
关于独立部署samba可参考:https://spredzy.wordpress.com/2013/08/30/samba-standalone-openldap/
======================分割线=======================
下面做samba使用ldap认证的配置
1
2
|
cp
/etc/samba/smb
.conf
/etc/samba/smb
.conf.bak
vi
/etc/samba/smb
.conf
|
[root@samba ~]# diff /etc/samba/smb.conf.bak /etc/samba/smb.conf
74c74
< workgroup = MYGROUP
---
> workgroup = contoso
77a78
> netbios name = Samba
109a111,116
> ldap group suffix = ou=group
> ldap user suffix = ou=People
> ldap delete dn = no
> ldap passwd sync = yes
> encrypt passwords = yes
再次修改了smb.conf文件,主要是修改了workgroup信息,并添加了ldap中的设置,比如默认添加用户到哪个ou中,添加组到哪个ou中去等。
1、创建本地用户
[root@samba ~]# useradd laowang
[root@samba ~]# echo "123456" |passwd --stdin laowang
Changing password for user laowang.
passwd: all authentication tokens updated successfully.
[root@samba ~]# id laowang
uid=500(laowang) gid=500(laowang) groups=500(laowang)
这里是演示新创建本地用户,然后通过smbpasswd -a添加到samba域,其实也可以不创建本地用户,直接使用ldap中现有的用户,然后使用smbpasswd -a添加,这里只是为了证明在使用smbpasswd -a添加后,openldap中能查询到新添加的用户。
2、创建samba域用户
[root@samba ~]# smbpasswd -a laowang
New SMB password:
Retype new SMB password:
Added user laowang.
3、到openldap server上查询刚刚创建的用户
[root@ldapsrv01 ~]# ldapsearch -x -LLL -D "cn=admin,dc=contoso,dc=com" -W -b "dc=contoso,dc=com" "(uid=laowang)"
Enter LDAP Password:
dn: uid=laowang,ou=People,dc=contoso,dc=com
uid: laowang
objectClass: sambaSamAccount
objectClass: account
objectClass: posixAccount
objectClass: shadowAccount
cn: lao wang
loginShell: /bin/bash
gecos: Ge bi lao wang
homeDirectory: /home/laowang
uidNumber: 10003
gidNumber: 10000
sambaSID: S-1-5-21-3657554500-457428447-597312458-500
sambaAcctFlags: [XU ]
sambaDomainName: SAMBA
displayName: laowang
sambaHomeDrive: U:
sambaPrimaryGroupSID: S-1-5-21-3657554500-457428447-597312458-513
sambaNTPassword: 32ED87BDB5FDC5E9CBA88547376818D4
sambaPwdLastSet: 1473757623
shadowLastChange: 17057
userPassword:: e1NTSEF9S0toc3UwbklHSjVaVkFHdThLVU1VN0xpbnRZM1pHMXo=
4、安装smaba client
1
|
yum -y
install
samba-client
|
5、使用laowang进行测试
[root@samba ~]# smbclient -L 127.0.0.1 -U laowang
Enter laowang's password:
Domain=[CONTOSO] OS=[Unix] Server=[Samba 3.6.23-36.el6_8]
Sharename Type Comment
--------- ---- -------
IPC$ IPC IPC Service (Samba Server Version 3.6.23-36.el6_8)
laowang Disk Home Directories
Domain=[CONTOSO] OS=[Unix] Server=[Samba 3.6.23-36.el6_8]
Server Comment
--------- -------
Workgroup Master
--------- -------
6、添加共享文件夹
编辑/etc/samba/smb.conf文件,并在其中添加如下内容:
[public]
comment = Public
path = /tmp
public = yes
writable = yes
printable = no
然后,重启smb服务。
7、测试共享文件
在Linux Client上测试:
[root@samba ~]# smbclient -L 127.0.0.1 -U laowang
Enter laowang's password:
Domain=[CONTOSO] OS=[Unix] Server=[Samba 3.6.23-36.el6_8]
Sharename Type Comment
--------- ---- -------
public Disk Public
IPC$ IPC IPC Service (Samba Server Version 3.6.23-36.el6_8)
laowang Disk Home Directories
Domain=[CONTOSO] OS=[Unix] Server=[Samba 3.6.23-36.el6_8]
Server Comment
--------- -------
Workgroup Master
--------- -------
在Windows上测试:
在资源管理器中输入:\\192.168.49.135\public,回车,在弹出窗口中输入用户名密码
下面我在public中创建一个名为laowang的文件夹,再在其中创建一个test.txt文本文件,写入“Hello world!”
回到samba服务器上查看/tmp目录下是否存在这个文件,
[root@samba ~]# ls /tmp/laowang/
test.txt
[root@samba ~]# cat /tmp/laowang/test.txt
Hello world!
可以看到刚刚写入的文件,说明共享成功,至此,samba整合openldap的过程彻底结束。
本文转自 jerry1111111 51CTO博客,原文链接:http://blog.51cto.com/jerry12356/1852375,如需转载请自行联系原作者