zoukankan      html  css  js  c++  java
  • 安全指导

    本章译者:@nixil

    虽然Play在设计之初就考虑了安全性问题,但是任何人都无法阻止程序员们自毁长城。以下的向导将会涉及web应用常见的安全性问题,以及在Play中该如何避免。

    Sessions

    你经常会需要保存一些跟用户有关的信息,比如登录状态之类的。如果没有session,用户就得在每个请求当中都携带认证信息。

    所谓session就是一组储存在用户浏览器的cookie中的数据,用于标识用户,有时候还会根据应用的需要存储一些额外信息,比如用户的语言之类的。

    安全第一要素 - 别把秘密公开

    session是一组键/值的哈希,它带有数字签名但是并未加密。这意味着,如果你的签名是安全的,任何第三方都无法伪造session。

    这个数字签名保存在@conf/application.conf@中. 一定要保证机密(数字签名)的私有性,绝对不要把它提交到公有代码库中。当你安装了一个由其他人构建的应用时,记得一定要用这个命令@play secret@,来修改原来的数字签名,。

    不在session中储存关键数据

    尽管有数字签名,但由于cookie是未加密的,你还是不应在session当中存储关键性数据。否则可能被通过查看cookie,或者在局域网/wifi的网关截获http请求等方式暴露。

    Play的session是存储在cookie中的,而cookie的大小被浏览器限制为4KB. 除了空间限制外, cookie中还仅能保存文本值。

    跨站脚本攻击

    跨站脚本攻击是web应用最大的弱点之一。其原理是在使用web应用的表单提交信息时,注入恶意JavaScript脚本. (这就好像送快递的往你家的邮箱里塞一个夹带了窃【听器的包裹)

    Let’s say you’re writing a blog, and anyone can add a comment. If you blindly include what commenters have written into your HTML page, you’re opening your site to attacks. It can be:

    • Show a popup to your visitors
    • Redirect your visitors to a site controlled by the attacker
    • Steal information supposed to be visible only to the current user, and send it back to the attacker’s site

    假设你有一个写博客的程序,而任何其它人都可以对博文添加评论,而评论最终会被显示在该。如果你允许评论者们将任何评论信息(比如一段html代码,其中可能还夹杂了javascript)内容提交到你的页面中,你的站点就会被攻击。可能会导致:

    • 你的blog的访客将会收到一个弹出窗,这可能只是恶搞一下
    • 你的blog的访客会被重定向到一个在攻击者控制之下的站点
    • 窃取到本应只有当前用户才能看到的信息,并将其发送到攻击者的站点。

    因此避开这些攻击是至关重要的

    Play的模板引擎会自动的将文本转义。如果你确实需要在模板中插入未转义的HTML,可以使用raw() 这个java扩展方法。但是如果文本是来自用户的输入,那你就要谨慎为之,确保先对这些输入进行“消毒”。

    审查用户输入的时候,使用“白名单(只允许某些安全标签)”比使用“黑名单(禁止某些不安全标签而允许其他标签)”来的安全。

    更多关于跨站脚本

    SQL 注入

    SQL注入是一种利用用户的输入来执行SQL脚本的攻击方式。这种攻击可能摧毁你的数据,也可能使你的数据暴露给攻击者。

    如果你使用高级的“find”方法,你必须考虑到对付SQL注入的问题。当你手工创建查询语句时,一定要小心不要使用字符串拼接(+)的方式传入参数,而应该使用@?@作为占位符然后替换。

    这种是安全的:

    createQuery("SELECT * from Stuff WHERE type= ?1").setParameter(1, theType);
    

    而这一种则是危险的:

    createQuery("SELECT * from Stuff WHERE type=" + theType;
    

    CSRF-跨站请求伪造

    CSRF-跨站请求伪造(又有戏称session-riding)也是web应用的一个大问题:

    这种攻击方法的前提是用户(在当前或者最近一段时间)登录了你的应用,浏览器中还保留着cookie。此时如果在该用户访问的某个页面(可能是任何一个其他的网站)中引入一段恶意的代码或者链接,使之向你的应用发起请求。那由于这个用户的session还没有过期,该请求就会利用这个“伪造”的session来通过应用的认证,执行恶意的操作了。

    要防止这种攻击,首先要正确的使用GET和POST方法. 也就是说,POST方法应该仅用于更改应用的状态. (而相应的GET方法不应该用于更改应用状态,这里也就是所谓的GET方法应该具有等幂性,这样一来攻击者就无法通过恶意的链接来执行恶意操作)。

    而对于接受POST请求的controller来说,保证每次收到的请求都是安全的方法之一,就是要求每个请求都提供一个认证口令(这个口令不是存放在cookie中而是作为随表单一起提交的一个隐藏字段)。Play提供了一些内置的帮助类和方法来处理这些事情。

    • controller中有一个@checkAuthenticity()@方法,它会检查包含在请求参数中的口令的合法性,如果发现不对就会返回一个forbidden(403)的响应。
    • session.getAuthenticityToken() 方法会生成一个仅对当前session有效的口令
    • 在html模板的form中使用 #{authenticityToken /} 会生成一个包含口令的隐藏域

    So for example:
    例如下面的代码(controller中的一个方法):

    public static destroyMyAccount() {
        checkAuthenticity();
        …
    }
    

    checkAuthenticity()会进行检查,只有提交的表单中包含正确的认证口令(模板中要加入如下面的代码)时才会执行

    <form method="post" action="/account/destroy">
        #{authenticityToken /}
        <input type="submit" value="destroy my account">
    </form>
    

    Play的“表单标签”: tags:#form 当其要提交到的action接受POST方法时会自动生成一个认证口令

    #{form @destroyMyAccount()}
        <input type="submit" value="destroy my account">
    #{/form}
    

    当然如果你想把对所有controller的访问都保护起来的话,你可以在增加一个controller的“before filter”: controllers#before,把@checkAuthenticity()@方法加在里面

    更多关于跨站请求伪造的信息

    Continuing the discussion

    Next: Play modules.

  • 相关阅读:
    【翻译】Flink Table Api & SQL —Streaming 概念 —— 时态表
    【翻译】Flink Table Api & SQL —Streaming 概念 ——在持续查询中 Join
    【翻译】Flink Table Api & SQL —Streaming 概念 ——时间属性
    【翻译】Flink Table Api & SQL —Streaming 概念 ——动态表
    【翻译】Flink Table Api & SQL ——Streaming 概念
    Kubernetes控制器之Deployment
    Kubernetes中nodeport,port,targetport对比
    Kubernetes控制器之ReplicaSet
    Kubernetes之Pods
    Kubernetes之使用ConfigMap配置Pod
  • 原文地址:https://www.cnblogs.com/zhiji6/p/4446839.html
Copyright © 2011-2022 走看看