[Playframework文档中文翻译]安全指导

(原文链接:http://play-framework.herokuapp.com/zh/security " ) 来自"Playframework中文小站 " )

安全指导

本章译者:@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()@方法加在里面

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

 

(原文链接:http://play-framework.herokuapp.com/zh/security " ) 来自"Playframework中文小站 " )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[强烈推荐, 文档不多, 很快就可以看完, 看完了, 就会使用play了] 目录 MVC应用程序模型 - 7 - app/controllers - 8 - app/models - 8 - app/views - 8 - 请求生命周期 - 8 - 标准应用程序布局layout - 9 - app目录 - 9 - public目录 - 10 - conf目录 - 10 - lib目录 - 11 - 开发生命周期 - 11 - 连接到java调试器 - 12 - 类增强Enhancement - 13 - 02.HTTP路由 - 13 - 关于REST - 14 - routes文件语法 - 14 - HTTP方法 - 15 - URI范示 Pattern - 15 - Java调用定义 - 17 - 把404当作action来用 - 17 - 指派静态参数 - 17 - 变量和脚本 - 18 - 路由优先级 - 18 - 服务器静态资源 - 18 - staticDir: mapping - 18 - staticFile: mapping - 19 - URL 编码 - 19 - 反转路由:用于生成某些URL - 19 - 设置内容风格(CSS) - 20 - HTTP 内容协商 negotiation - 21 - 从http headers开始设置内容类型 - 21 - 定制格式 - 22 - 03.控制器 - 23 - 控制器概览 - 23 - 获取http参数 - 24 - 使用params map - 25 - 还可以从action方法签名实现转换 - 25 - 高级HTTP Java绑定 - 26 - 简单类型 - 26 - Date类型 - 26 - Calendar日历 - 27 - File - 27 - 支持类型的数组或集合 - 28 - POJO对象绑定 - 29 - JPA 对象绑定 - 30 - 定制绑定 - 30 - @play.data.binding.As - 30 - @play.data.binding.NoBinding - 31 - play.data.binding.TypeBinder - 31 - @play.data.binding.Global - 32 - 结果类型 - 32 - 返回一些文本类型的内容 - 33 - 返回一个JSON字符串 - 33 - 返回一个XML字符串 - 34 - 返回二进制内容 - 34 - 作为附件下载文件 - 34 - 执行一个模板 - 35 - 跳转到其他URL - 36 - Action链 - 36 - 定制web编码 - 37 - 拦截器 - 38 - @Before - 38 - @After - 39 - @Catch - 40 - @Finally - 41 - 控制器继承 - 42 - 使用@With注释添加更多的拦截器 - 42 - Because Java does not allow multiple inheritance, it can be very limiting to rely on the Controller hierarchy to apply interceptors. But you can define some interceptors in a totally different class, and link them with any controller using the @With annotation.由于java不允许多继承,通过控制器继承特点来应用拦截器就受到极大的限制。但是我们可以在一个完全不同的类里定义一些拦截器,然后在任何控制器里使用@With注释来链接他们。 - 42 - Session和Flash作用域 - 42 - 04.模板引擎 - 43 - 模板语法 - 43 - Expressions: ${…} - 44 - Template decorators : #{extends /} and #{doLayout /} - 44 - Tags: #{tagName /} - 45 - Actions: @{…} or @@{…} - 46 - Messages: &{…} - 46 - Comment: *{…}* - 46 - Scripts: %{…}% - 46 - Template inheritance继承 - 47 - 定制模板标签 - 48 - 检索tag参数 - 48 - 调用标签体 - 48 - 格式化特定标签 - 49 - 定制java标签 - 49 - 标签命名空间 - 50 - 在模板里的Java对象扩展 - 51 - 创建定制扩展 - 52 - 模板里可以使用的保留对象 - 52 - 05.用play验证http数据 - 53 - 在play里验证如何进行的? - 53 - 验证的错误消息 - 54 - Localised validation messages 局部验证消息 - 55 - 验证消息参数 - 55 - 定制局部验证消息 - 56 - 定制teral(非局部)验证消息 - 57 - 在模板里显示验证错误消息 - 57 - 验证注释 - 60 - 验证复杂对象 - 60 - 内建验证 - 61 - 使用@CheckWith定制验证 - 61 - 定制注释 - 62 - 06.域对象模型 - 64 - 属性模仿 - 65 - 设置数据库来持久化模型对象 - 68 - 用hibernate持久化对象模型 - 69 - 保持模型stateless - 70 - 07.JPA持久化 - 70 - 启动JPA实体管理器 - 70 - 获取JPA实体管理器 - 70 - 事务管理 - 71 - play.db.jpa.Model支持类 - 71 - 为GenreicModel定制id映射 - 72 - Finding对象 - 72 - Find by ID - 72 - Find all - 73 - 使用简单查询进行查找 - 73 - 使用JPQL 查询进行查找 - 74 - Counting统计对象 - 74 - 用play.db.jpa.Blob存储上传文件 - 74 - 强制保存 - 75 - 更多公共类型generic typing问题 - 77 - 08.Play.libs库包 - 78 - 用XPath解析XML - 78 - Web Service client - 79 - Functional programming with Java功能扩展? - 79 - Option<T>, Some<T> and None<T> - 80 - Tuple<A, B> - 80 - Pattern Matching模式匹配 - 81 - Promises - 81 - OAuth - 82 - OAuth 1.0 - 82 - OAuth 2.0 - 83 - OpenID - 84 - 09.异步Jobs - 86 - 引导程序任务Bootstrap jobs - 87 - 预定义任务Scheduled jobs - 87 - 触发任务job - 88 - 停止应用程序 - 89 - 10.在HTTP下进行异步编程 - 89 - 暂停http请求 - 89 - Continuations - 90 - 回调Callbacks - 91 - HTTP response流 streaming - 92 - 使用WebSockets - 92 - 11.在play框架里使用Ajax - 94 - 通过jsAction标签使用jQuery - 95 - 12. Internationalization国际化支持 - 96 - 仅使用 UTF-8! - 96 - 国际化你的信息 - 96 - 通过应用程序定义支持的语言 - 96 - 依照你的区域定义日期格式 - 97 - 找回区域信息 - 97 - Message arguments - 97 - 模板输出 - 98 - 多参数 - 98 - 立即数Argument indices - 98 - 13.使用cache - 99 - The cache API - 99 - 不要把Session当成缓存! - 101 - 配置mcached - 101 - 14.发送e-mail - 102 - Mail 和MVC 集成 - 102 - text/html e-mail - 103 - text/plain e-mail - 104 - text/html e-mail with text/plain alternative - 104 - 在应用程序里链接到邮件 - 104 - SMTP配置 - 105 - 使用 Gmail - 105 - 15.测试应用程序 - 105 - 书写测试程序 - 105 - 单元测试 - 106 - 功能性测试 - 106 - Selenium test用例测试 - 107 - Fixtures固定值 - 108 - 运行测试 - 110 - 陆续集成,并自动运行测试 - 111 - 16.安全指南 - 112 - Sessions - 112 - 守住你的安全安全 - 112 - 不要存储关键性的数据 - 112 - 跨站点脚本攻击 - 112 - SQL注入 - 113 - 跨站点请求伪造 - 114 - 17.Play模块和模块仓库 - 115 - 什么是模块? - 115 - 如何从一个应用程序里加载模块 - 115 - 从模块加载默认的routes - 115 - 为模块增加文档说明 - 115 - 使用模块仓库 - 116 - 贡献新模块到模块仓库里 - 117 - 先决条件 - 117 - 模块注册 - 117 - 发布你的模块 - 118 - 18.依赖管理 - 118 - 依赖格式 - 119 - 动态版本 - 119 - dependencies.yml - 119 - ‘play dependencies’命令 - 120 - 透明依赖 - 121 - 保持lib/和modules/目录同步 - 122 - 冲突判定Conflict resolution - 123 - 增加要的仓库 - 124 - Maven仓库 - 125 - 本地仓库 - 125 - 定制ivy设置(Apache ivy:项目依赖管理工具) - 126 - 清除Ivy缓存 - 127 - 19.管理数据库变化Evolution - 128 - Evolutions脚本 - 128 - 同步同时发生的改变 - 130 - 数据不一致状态 - 133 - Evolutions 命令 - 136 - 20.日志配置 - 139 - 对应用程序进行日志 - 139 - 配置日志级别 - 140 - 生产配置 - 140 - 21.管理多环境下的application.conf - 140 - 框架id(framework ID) - 141 - 从命令行设置框架id - 142 - 22.生产部署 - 142 - application.conf - 142 - 设置框架为prod模式: - 142 - 定义一个真实的数据库: - 143 - 禁止JPA的自动结构更新: - 143 - 定义一个安全的secret key: - 143 - 日志配置 - 143 - 前端http服务器(Front-end HTTP server) - 144 - 部署到lighttpd服务器的设置 - 144 - 部署到Apache服务器的设置 - 145 - Apache作为前端代理服务器,可以允许透明更新你的应用程序 - 145 - 高级代理设置 - 146 - HTTPS配置 - 147 - 不依赖Python进行部署 - 148 - 23.部署选择 - 148 - 独立Play应用程序 - 149 - Java EE应用服务器 - 149 - 支持应用服务器 - 149 - 部署 - 150 - 数据源 - 150 - 定制web.xml - 151 - 基于云的主机Cloud-based hosting - 151 - AWS Elastic Beanstalk - 152 - CloudBees - 152 - Cloud Foundry - 152 - Google App Engine (GAE) - 152 - Heroku - 152 - playapps.net - 153 -
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值