在PlayFramework下隐藏后台管理员登录界面的两种方法(限制IP和HTTPS)

最近在做一个网站,网站的内容有些是要管理员修改的,比如招聘信息等,但要修改的信息不是很多,因为想要尽可能的提高安全性,对管理后台的登录做了一些限制,首先想到的是对登录IP做限制,但是现在我们使用的宽带基本上都是动态IP,所以会给用户带来很多不便,于是想到了使用HTTPS,本文讲对这两种方法进行讨论,并给出相应实现。我是在Play framework的环境中开发,但是这个配置流程是普适的。

    1. 绑定IP


这个方法相当简单,在Play的Controller中使用request().remoteAddress()获取远程IP,然后对用户名进行匹配。

如果用户访问/admin/login这种地址,先判断他的IP是否在允许的IP范围内,如果不在,直接重定向到主页,入侵者是不知道这个地址是不存在,还是他的权限不能访问。

    2. 使用HTTPS双向验证


使用HTTPS双向验证并不能够达到管理登录的地址完全对用户透明,使用“绑定IP”的方法,当用户不在允许的IP地址访问/admin/login这种地址,后台可以直接把他重定向到/index, 但是使用HTTPS需要重定向到HTTPS的地址,大致的步骤如下:

  1. 用户访问http://abcd.com/admin/login
  2. 后台将用户重定向到https://abcd.com/admin/login
  3. 后台验证用户的客户端证书
  4. 如果3验证失败,则浏览器会访问错误
  5. 如果3验证成功,则访问真正的管理员登录界面
  6. 用户登录后,后台将用户重定向到http://abcd.com/admin

在这个过程中,入侵者是可以知道这个地址存在的,只是他不能访问而已,如果在后台能拦截到第3步验证失败的情况,就可以避免这个信息被泄露了。
那么要实现这个步骤,需要开发者实现自定义的SSLEngineProvider, Play默认的SSLEnginProvider没有双向验证的功能,源代码可以在这里找到:https://github.com/playframework/playframework/blob/master/framework/src/play-server/src/main/scala/play/core/server/ssl/DefaultSSLEngineProvider.scala#L27
自定义的SSLEngineProvider如下:

File serverFile = play.Play.application().getFile(“conf/server.jks”);
File clientFile = play.Play.application().getFile(“conf/clients.jks”);
// 载入server端私钥
ks.load(new FileInputStream(serverFile), passphrase);
// 载入client可信证书,获取客户端公钥
ts.load(new FileInputStream(clientFile), clientPass);

KeyManagerFactory kmf = KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
kmf.init(ks, passphrase);

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ts);

SSLContext sslCtx = SSLContext.getInstance(“TLS”);

sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
return sslCtx.createSSLEngine();

然后在application.conf或者命令行中加入play.server.https.engineProvider=customizedProvider。
Play默认使用JKS作为证书存储可是,你也可以用其他的格式,但这个是比较简单的,以上代码中用到两个jks文件:server.jks存储了服务器做签名使用到的证书链(公钥和私钥),client中存储了允许访问此网站的证书(只需要是公钥)。

以下是两个证书文件的生成步骤

准备工作:

  • openssl
  • KeyTool(不是必须)
  • demoCA文件夹,可以在默认的openssl.conf中修改,如果使用默认的配置文件,其目录如下
    https://www.openssl.org/docs/manmaster/apps/ca.html

tree demoCA/
demoCA/
├── cacert.pem //必须 CA证书
├── index.txt //必须 序列号
├── index.txt.attr
├── index.txt.attr.old
├── index.txt.old
├── newcerts
│   ├── 01.pem
│   ├── 02.pem
│   └── 03.pem
├── private
│   └── cakey.pem //必须 CA的私钥
├── serial //必须 存储签名后的证书
└── serial.old

这是在openssl网站与次相关的一段描述:

To use the sample configuration file below the directories demoCA, demoCA/private and demoCA/newcerts would be created. The CA certificate would be copied to demoCA/cacert.pem and its private key to demoCA/private/cakey.pem. A file demoCA/serial would be created containing for example “01” and the empty index file demoCA/index.txt.

这里我的服务器证书使用了一个二级证书,多级证书以此类推都是一样的,生成server.jks的步骤:

1)生成CA(如果你的网站是买的证书,这一步可省略)


openssl genrsa -out cakey.pem 2048
openssl req -new -x509 -key cakey.pem -out cacert.pem
或者使用sha256
openssl req -new -x509 -key cakey.pem -out cacert.pem -sha256 -days 3650

2) 生成服务器证书请求(分别使用keytool和openssl)


openssl的方法:

openssl genrsa -des3 -out server.key 2048
openssl req -new -key server.key -out server.csr
或者使用sha256
openssl req -out CSR.csr -key key_name.key -new -sha256

key tool的方法:

$ keytool -genkey -alias server1 -keyalg rsa -keystore server.jks

keytool -certreq -alias server1 -keystore server.jks -file server.csr

3)使用CA签名(或者向你的CA购买签名)


openssl ca -in server.csr -out server.crt -config ./openssl.cnf -extfile ca-extensions.ext -days 1500
Using configuration from ./openssl.cnf
Check that the request matches the signature
Signature ok
The countryName field needed to be the same in the
CA certificate (CN) and the request (Unknown)

4)导出可安装的p12格式的证书密钥对


openssl pkcs12 -export -clcerts -in lingling.crt -inkey lingling.key -out lingling.pfx

另外在极少数情况下,上面的命令生成的证书不能识别,试试下面的命令:
# openssl x509 -req -in server.csr -CA /etc/pki/CA/cacert.pem -CAkey /etc/pki/CA/private/cakey.pem -CAcreateserial -out server.crt

4)将签名后的证书导入server.jks


这里一定要先将一整个证书链从CA开始完全导入jks,最后再导入真正使用的上一步生成的server.crt
keytool -import -trustcacerts -file ca.crt -alias root -keystore server.jks

keytool -import -trustcacerts -file server.crt -alias server -keystore server.jks

5) 生成客户端证书的根证书(也可以是二级证书),并导入client.jks。与第一步相同

6)之后就可以从#5中生成的根(或者中间证书)来签名客户端证书,他们都会服务器被接受

一些有用的信息:


如何从keytool生产的证书对中获取私钥:
1、从JKS转换到PKCS12
D:\ssl>keytool -importkeystore -srckeystore keystore_old.jks -destkeystore keystore_old.p12 -srcstoretype JKS -deststoretype PKCS12 -srcstorepass changeit -deststorepass changeit -srcalias tom_server -destalias xxx -srckeypass changeit -destkeypass changeit -noprompt

2、从PKCS12转换成PEM格式
openssl pkcs12 -in keystore_old.p12 -out keystore_old.pem -passin pass:changeit -passout pass:changeit

3、用记事本打开PEM格式文件,从PEM格式的certificate chain中取出私钥,保存为privateKey.key

4、生成私钥

私钥将被显示在命令行界面上

openssl rsa -in privateKey.key -check

KK笔记:kknotes.com
本文链接地址: 在PlayFramework下隐藏后台管理员登录界面的两种方法(限制IP和HTTPS)

转载须以超链接形式标明文章原始出处和作者信息及版权声明

未经允许不得转载:KK笔记 » 在PlayFramework下隐藏后台管理员登录界面的两种方法(限制IP和HTTPS)

赞 (0)

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址