摘要:设置验证码任何人都可以在我们的博客下发布评论,所以我们需要避免非人类用户来扰乱秩序。一个简单的防范方法是设置验证码。然后我们修改表单来显示验证码,并把写入隐藏的域里面。检查验证码功能是否完成了。
设置验证码
任何人都可以在我们的博客下发布评论,所以我们需要避免非人类用户来扰乱秩序。一个简单的防范方法是设置验证码。
生成验证码如何利用Play框架来生成验证码?简单来说,我们需要增加一个action,不过让它返回的是一个二进制的对象而不是之前的HTML页面。
因为Play是一个全栈式框架,我们试图在框架内部内置了Web应用通常所需的东西;其中就包括生成验证码。我们可以使用play.libs.Images来简单地生成验证码,然后通过HTTP响应返回它。
如常,我们先从一个原型开始。在Applicantion控制器中添加captcha action。
public static void captcha() { Images.Captcha captcha = Images.captcha(); renderBinary(captcha); }
注意我们可以直接传递captcha对象给renderBinary(),因为Images.Captcha类实现了java.io.InputStream。
请勿忘记导入play.lib.*
现在向/yabe/conf/routes添加新路由:
GET /captcha Application.captcha
然后打开http://localhost:9000/captcha看看效果。
每次刷新时应该会产生随机的文字
我们怎样管理状态?目前为止事情顺利,但是最复杂的部分就要来了。要想验证验证码,我们需要保存验证码图片上的文字,然后跟提交的表单进行比对。
当然我们可以把文字存储在用户会话中,然后在验证时再提取出来。但这样做有两个问题:
首先,Play的会话是存储在cookie里的。这样解决了一些架构上的问题,但是也引入一些麻烦。写入到cookie的数据是签了名的,这样用户就不能修改它;但是它并未加密。如果我们把验证码的内容写入cookie,每个人都可以读到它 —— 然后破解它。
其次,不要忘了Play是一个无状态的框架。我们想要在无状态的情况下管理事务。假如一个用户同时打开两个不同的博客页面,生成了不同的验证码,我们就需要跟踪处理对应的验证码。
所以要想解决问题,我们需要两样东西。我们得在服务器存储验证码的密钥。因为它是一个临时数据,我们可以存储在Play缓存(Cache)中。此外,这样做还可以增加安全性,因为存储在缓存中的数据的生命期是有限的(比如10分钟)。然后我们还需要生成独一无二的ID。这个ID将添加到每个表单的隐藏域中,对应着一个生成的验证码。
下面让我们来解决这个问题吧。
修改captcha action成这样:
public static void captcha(String id) { Images.Captcha captcha = Images.captcha(); String code = captcha.getText("#E4EAFD"); Cache.set(id, code, "10mn"); renderBinary(captcha); }
注意getText()方法接受任意颜色作为参数。它需要输入的颜色来画文本。
添加验证码到评论框请勿忘记导入play.cache.*。
现在,在显示一个评论框之前我们先生成一个独一无二的ID。然后我们修改HTML表单来显示验证码,并把ID写入隐藏的域里面。
让我们重写Application.show action:
public static void show(Long id) { Post post = Post.findById(id); String randomID = Codec.UUID(); render(post, randomID); }
以及/yable/app/views/Application/show.html模板中的表单:
…
…
好棒,现在评论框里能看到验证码了。
验证验证码现在来验证验证码吧。我们添加了randomID作为隐藏域对吧?那就在postComment里面把它提取出来,然后取出缓存中对应的编码,最后跟提交的输入进行比对。
这一点都不难。让我们来修改postComment方法。
public static void postComment( Long postId, @Required(message="Author is required") String author, @Required(message="A message is required") String content, @Required(message="Please type the code") String code, String randomID) { Post post = Post.findById(postId); validation.equals( code, Cache.get(randomID) ).message("Invalid code. Please type it again"); if(validation.hasErrors()) { render("Application/show.html", post, randomID); } post.addComment(author, content); flash.success("Thanks for posting %s", author); Cache.delete(randomID); show(postId); }
因为现在有不同的错误信息,而我们只想显示第一条信息,所以修改show.html模板中显示错误的部分:
.. #{ifErrors}${errors[0]}
#{/ifErrors} …
对于一个更加复杂的表单,错误信息不应该这样管理,而应该集中到一个讯息文件中,并且每个错误都应该在对应的区域内显示。
检查验证码功能是否完成了。
耶!
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/64100.html
摘要:完成应用测试我们已经完成了我们想要创建的博客引擎。当然我们已经完成了测试所有模型层的功能。评估代码覆盖率当然我们还没有完成应用所需的所有测试用例。如你所见,我们远远没有完成对应用的全面测试。 完成应用测试 我们已经完成了我们想要创建的博客引擎。不过这个项目尚未完全结束。为了保证代码的质量,我们需要添加更多的测试。 当然我们已经完成了测试所有模型层的功能。所以博客引擎的核心功能已经被...
摘要:确保你的文本编辑器已经做了相应的配置。第一个,会自动监测源代码的改变并在运行时自动重载。检查下面的一行是否出现在应用日志中使用版本控制系统来追踪变化当你开发一个项目时,最好使用版本控制系统来存储你的源代码。 Play是一个Java Web敏捷开发的框架http://www.playframework.com/documentation/1.2.7/home 之所以要翻译这个教程,是因...
摘要:浏览和提交评论博客主页现在已经完成,接下来要完成博客正文页面。整个页面将展示当前文章的所有评论,还包括一个用于提交新的评论的表单。刷新浏览器,检查这次是否使用了正确的。给模板添加表单在后面试下提交新的评论。 浏览和提交评论 博客主页现在已经完成,接下来要完成博客正文页面。整个页面将展示当前文章的所有评论,还包括一个用于提交新的评论的表单。 创建show action 要显示文章内...
摘要:添加验证既然我们有一个管理面板,自然需要进行验证。自定义验证过程你可以用应用提供的实例来自定义验证过程。通过继承自该类,我们可以指定验证用户的方式。这个将给每个作者发布自己的文章的权限。现在在添加到控制器的链接接下来是创建模板。 添加验证 既然我们有一个管理面板,自然需要进行验证。幸运的是,Play已经提供了一个叫做Secure的模块来帮助我们。 启动Secure模块 在yabe/co...
摘要:通过来实现一个基本的管理面板目前,我们还没法使用博客的来写新的文章,或修改评论。提供了一个即开即用的模块,可以快速生成一个基本的管理面板。这是因为默认是以的输出来得到一个模型对象的表示。在本教程的最后一章,你会学到关于本地化信息的更多东西。 通过CRUD来实现一个基本的管理面板 目前,我们还没法使用博客的UI来写新的文章,或修改评论。Play提供了一个即开即用的CRUD模块,可以快速...
阅读 2570·2023-04-25 17:33
阅读 650·2021-11-23 09:51
阅读 2953·2021-07-30 15:32
阅读 1400·2019-08-29 18:40
阅读 1942·2019-08-28 18:19
阅读 1467·2019-08-26 13:48
阅读 2239·2019-08-23 16:48
阅读 2277·2019-08-23 15:56