使用Mozilla Persona认证用户的指南

到目前为止,只有Twitter和Facebook身份验证,我决定将Mozilla Persona添加到我最新项目( 计算机 ,计算机生成的音乐)的列表中。 为什么?

  • 我喜欢尝试新事物
  • 存储密码是一个艰巨的过程,尽管我知道该怎么做,甚至大部分代码都写在另一个项目中,但我认为我不应该为每个需要密码认证的站点做出贡献
  • Mozilla是一个开放的基金会,迄今为止已经产生了许多出色的产品。 Persona实现了BrowserID协议,将来可能会在Firefox以外的其他浏览器中本地支持(目前,您需要包含.js文件)
  • 第三方身份验证已经尝试了很多次,这是一件很了不起的事情,但是由于一些原因,它并不是主流。 有所不同,《女神异闻录》可能会成功地变得更受欢迎。
  • Mozilla的解释很有意义

因此,我从“快速设置”指南开始。 看起来真的很容易。 比OpenID或OAuth身份验证容易得多–您无需在任何地方注册任何内容,不需要第三方库来在服务器上处理验证,并且您无需学习复杂的身份验证流程,因为该流程很简单:

  1. 用户单击登录按钮
  2. 出现一个弹出窗口
  3. 如果未通过Persona认证,则提示用户注册
  4. 如果通过Persona进行了身份验证,则提示用户批准对该站点的身份验证
  5. 弹出窗口关闭,页面重定向/刷新-用户现在已登录

当然,它不是那么简单,但是有一些需要注意的地方在本教程中没有提到。 因此,让我们一步一步地遵循官方教程,并且我将在每一点上进行扩展(使用的服务器端语言是Java,但它很简单,您可以使用任何语言来完成)

1.包括.js文件-简单。 建议从Mozilla服务器获取js文件,而不是将其存储在本地,因为它可能会更改(例如,为了修复错误)。 如果将js文件合并到一个文件中(为了更快地加载页面)可能会比较棘手,但是可能您的机制允许加载远程js文件。

2.登录和退出按钮。 这看起来也很容易。 最好有条件地添加注销处理程序–仅当用户已使用Persona登录时(而不是您的站点支持的其他身份验证方法)

3.侦听身份验证事件。 建议将侦听事件放在所有页面上(例如,包含在标题模板中)。 但是这里有个问题。 如果您的用户已经在Persona中进行了身份验证,但是他的会话在您的站点上已过期,则脚本将自动登录该用户。 这将需要在页面加载后的几秒钟内重新加载页面。 这并不一定是您或用户想要的-例如,在我的情况下,这可能意味着他们刚刚播放的曲目由于页面刷新而中断。 当然可以使用AJAX来完成,但是当UI中的某些内容没有明显原因发生更改时,肯定会造成混乱。 下面,我将显示针对此问题的修复程序。 另外,注销侦听器可能并不是到处都需要的-据我了解,万一您注销了Persona,它将自动注销用户。 这可能不是您想要的,例如,用户可能希望保留一些打开的选项卡,其中某些文件在注销时无法访问。

4.验证服务器上的断言。 在这里,您可能需要第3方库来调用验证端点并解析json结果,但是这些是您可能已经包含的非常标准的库。

现在,如何解决自动身份验证的问题? 声明一个新变量userRequestedAuthentication ,该变量保存身份验证是由用户显式发起还是由用户自动发起。 在登录按钮中,单击处理程序,将该变量设置为true 。 这是js代码的样子(顺便说一句,我认为可以将代码放在document.ready()中,而不是直接放在script标记中。假设您以后需要在处理程序方法中使用一些DOM资源,页面已完全加载。另一方面,这可能会减慢该过程的速度)。 请注意,您可以在所有页面上包括一个空的onlogin处理程序,并且仅在身份验证页面上具有完整的处理程序。 但是,鉴于登录按钮位于主页上,或带有javascript模态窗口,因此可以在任何地方/在多个页面上都可以使用。

<script type='text/javascript'>var loggedInUser = ${context.user != null ? ''' + context.user.email + ''' : 'null'};var userRequestedAuthentication = false;navigator.id.watch({loggedInUser : loggedInUser,onlogin : function(assertion) {$.ajax({type : 'POST',url : '${root}/persona/auth',data : {assertion : assertion, userRequestedAuthentication : userRequestedAuthentication},success : function(data) {if (data != '') {window.location.href = '${root}' + data;}},error : function(xhr, status, err) {alert('Authentication failure: ' + err);}});},onlogout : function() {window.locaiton.open('${root}/logout');}});
</script>

如您所见,参数被传递到服务器端代码。 那里发生了什么?

@RequestMapping('/persona/auth')
@ResponseBody
public String authenticateWithPersona(@RequestParam String assertion,@RequestParam boolean userRequestedAuthentication, HttpServletRequest request, Model model)throws IOException {if (context.getUser() != null) {return '';}MultiValueMap<String, String> params = new LinkedMultiValueMap<>();params.add('assertion', assertion);params.add('audience', request.getScheme() + '://' + request.getServerName() + ':' + (request.getServerPort() == 80 ? '' : request.getServerPort()));PersonaVerificationResponse response = restTemplate.postForObject('https://verifier.login.persona.org/verify', params, PersonaVerificationResponse.class);if (response.getStatus().equals('okay')) {User user = userService.getUserByEmail(response.getEmail());if (user == null && userRequestedAuthentication) {return '/signup?email=' + response.getEmail();} else if (user != null){if (userRequestedAuthentication || user.isLoginAutomatically()) {context.setUser(user);return '/';} else {return '';}} else {return ''; //in case this is not a user-requested operation, do nothing}} else {logger.warn('Persona authentication failed due to reason: ' + response.getReason());throw new IllegalStateException('Authentication failed');}
}

逻辑看起来比您希望的更复杂,但是让我解释一下:

  • 正如您在javascript代码中看到的那样,空字符串表示“不执行任何操作”。 如果返回任何其他内容,则javascript将打开该页面。 如果不使用spring-mvc,则无需将其从方法中返回@ResponseBody字符串,而是将其写入响应输出流中(或用php术语–将其回显)。
  • 首先,您检查系统中是否已经有经过身份验证的用户。 如果有,则什么也不做。 我不确定是否存在Persona在已通过身份验证的用户上调用“ onlogin”的情况,但是如果您使用其他身份验证选项,Persona不会知道您的用户已经使用Twitter登录。
  • 然后,您调用验证URL并将结果解析为JSON。 我已经使用过RestTemplate ,但是任何东西都可以使用RestTemplate ,URLConnection。 对于JSON解析,spring在后台使用了Jackson。 您只需要编写一个值对象,即可保存Persona可能返回的所有属性。 到目前为止,我只包括:状态,电子邮件和原因(杰克逊详细信息:ignoreUnknown = true,spring-mvc详细信息:您需要将FormHttpMessageConverter设置为RestTemplate )。 重要的是,“受众”参数必须是用户当前所在的域。 无论是否使用www,它都会有所不同,因此请对其进行重构,而不是对其进行硬编码或从属性中加载它。 即使您从www重定向到no-www(反之亦然),您仍应为测试而动态获取该URL –测试环境的URL与生产环境的URL不同。
  • 如果Persona身份验证为“可以”,则您尝试在数据库中查找具有该电子邮件的用户。
  • 如果没有这样的用户,并且已手动触发了身份验证操作,则将用户发送到注册页面并提供电子邮件作为参数(您也可以在http会话中进行设置,以使用户无法对其进行修改)。 然后,注册页面会询问其他详细信息-名称,用户名,出生日期或您认为合适的任何信息(但请尽量减少-最好仅是全名)。 如果仅需要电子邮件地址,而无需其他任何内容,则可以跳过注册页面并强制注册用户。 注册完成后,您登录用户。 请注意,如果您已将电子邮件存储在会话中(即用户无法从注册页面进行修改),则可以跳过确认电子邮件-Persona已确认该电子邮件
  • 如果您的数据库中有一个使用该电子邮件的用户,请检查该用户是否已请求该操作,或者是否已(通过注册页面中的复选框)指示他要自动登录。考虑–应该询问用户,还是应该始终将其设置为true或false? 我已经添加了复选框。 如果应该登录,则将用户设置在会话中,然后重定向到home(或上一页,或“用户home”的任何页面)(“ context”是会话范围的Bean。您可以将其替换为session.setAttribute('user', user) )。 如果身份验证尝试是自动的,但用户不希望这样做,则不执行任何操作。 最后一个“其他”是针对用户在您的站点上没有帐户并且触发了自动身份验证的情况–在这种情况下不执行任何操作,否则最终将无休止地重定向到注册页面
  • 如果验证失败,请务必记录原因-然后您可以通过查看日志来检查一切是否正常

使用电子邮件作为唯一标识符的一个很酷的副作用是(如果使数据库列成为唯一 ),如果稍后将Persona添加到您的网站,即使用户以其他方式注册(例如,facebook或常规注册),用户也可以登录。 因此,他们可以将密码设置为长而难以记住的密码,并仅使用Persona继续登录。

我从实现中省略的细节很简单:注册页面只是收集字段并将其提交给/ completeRegistration处理程序,该处理程序将新用户存储在数据库中。 / logout URL仅清除会话(如果存储了cookie,则清除cookie)。 顺便说一句,如果启用了自动登录,并且Persona是您唯一的身份验证方法,则可能不需要存储cookie来保持会话过期后仍保持用户登录状态。

总体而言,即使我提出了要点,实现也仍然很简单。 女神异闻录看起来很棒,我希望很快能在更多站点上看到它。

参考: Bozho的技术博客博客上的JCG合作伙伴 Bozhidar Bozhanov的 Mozilla Persona身份验证用户指南 。

翻译自: https://www.javacodegeeks.com/2012/12/a-guide-to-authenticating-users-with-mozilla-persona.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/369742.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python字典与json转换_python字典与json转换的方法总结

在python中json分别由列表和字典组成&#xff0c;本文主要介绍python中字典与json相互转换的方法。使用json.dumps可以把字典转成json字符串。使用json.loads可以把json字符串转为字典类型的数据。1、字典转json使用json.dumpsjson.dumps是对python对象编码成json对象&#xff…

变量声明declare,简单运算符运算,变量测试与内容替换

declare -/ 选项 变量名 - 设类型 取消类型 -i 设为整型 -x 设为环境变量 -p 显示类型属性&#xff08;property&#xff09; [rootlocalhost ~]# a1 [rootlocalhost ~]# declare -p a declare -- a"1" [rootlocalhost ~]# export a [rootlocalhost ~]# declare -p …

如何水平居中一个元素

在项目中经常会遇到居中问题&#xff0c;这里借鉴度娘的众多答案&#xff0c;做一个总结&#xff1a; 一、元素的水平居中 1、行级元素的水平居中 <div style"width: 200px;height: 100px;border: 1px solid cyan; text-align: center;"><span>行级元素…

Yammer Metrics,一种监视应用程序的新方法

当您运行诸如Web应用程序之类的长期应用程序时&#xff0c;最好了解一些关于它们的统计信息&#xff0c;例如&#xff0c;服务的请求数&#xff0c;请求持续时间或活动请求数。 但是还有一些更通用的信息&#xff0c;例如内部集合的状态&#xff0c;代码的某些部分被执行了多少…

mysql教程目录_MySql目录(二)

MySql索引(二) 转自&#xff1a; http://www.cnblogs.com/dreamhome/archive/2013/04/16/3025304.html 所有MySQL列类型可以被索引。根据存储引擎定义每个表的最大索引数和最大索引长度。 所有存储引擎支持每个表至少16个索引&#xff0c;总索引长度至少为256字节。大多数存储引…

solr和Lucene的配置方式和应用

solr字段类型 类说明BinaryField二进制数据BoolField布尔值&#xff0c;其中’t’/’T’/’1’都是trueCollationFiled支持Unicode排序CurrencyField支持货币和汇率DateRangeFiled支持索引date rangeExternamFiledFiledpull磁盘上的文件EnumField支持定义枚举值ICUCollationFie…

PostgreSQL 9.6 keepalived主从部署

## 环境&#xff1a; PostgreSQL版&#xff1a;9.6 角色 OS IPmaster CentOS7   10.100.12.73 slave CentOS7 10.100.12.74 vIP 10.1…

CSS——清除浮动的六种解决方案

内容的高度撑起父元素容器的高度&#xff0c;效果图如下HTML和CSS代码如下给&#xff50;标签加上浮动以后&#xff0c;&#xff50;&#xff5b;float&#xff1a;left&#xff1b;&#xff5d;&#xff0c;此时DIV塌陷&#xff0c;两段内容同行显示&#xff0c;效果如下&…

40个Java Collections面试问答

Java Collections Framework是Java编程语言的基本方面。 这是Java面试问题的重要主题之一。 在这里&#xff0c;我列出了Java集合框架的一些重要问题和解答。 什么是Java Collections Framework&#xff1f; 列出Collections框架的一些好处&#xff1f; 集合框架中泛型的好处…

vs mysql iss_MySQL5.7与8.0的连接问题(vs2015\2017)

1.MySQL8.0 root密码忘记重置与5.7不同&#xff0c;绝大多数经验帖不适用8.0https://dev.mysql.com/doc/refman/8.0/en/resetting-permissions.html8.0 重置密码的方式2.MySQL连接vs2015时报错提示&#xff1a;Authentication method ‘caching_sha2_password‘ not supported …

191. Number of 1 Bits

Write a function that takes an unsigned integer and returns the number of ’1 bits it has (also known as the Hamming weight). For example, the 32-bit integer ’11 has binary representation 00000000000000000000000000001011, so the function should return 3. …

AtCoder Beginner Contest 084(AB)

A - New Year 题目链接&#xff1a;https://abc084.contest.atcoder.jp/tasks/abc084_a Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement How many hours do we have until New Year at M oclock (24-hour notation) on 30th, December? Cons…

打开就随机生长的树

今天接触了一个新东西&#xff0c;感觉很酷炫的样子。不是我写的&#xff0c;拿给大家看一看&#xff0c;喜欢的可以直接拿走不谢。树的形状和树枝多少都是随机的&#xff0c;每刷新一次就有一次的惊喜哦&#xff0c;无聊的亲们可以多刷几次&#xff0c;当动画来看哦。2017年又…

等待正确的时刻–集成测试

当您必须测试多线程程序时&#xff0c;总是需要等到系统达到特定状态后&#xff0c;测试才能验证是否达到了正确的状态。 这样做的通常方法是在系统中插入一个“探针”&#xff0c;该探针将向同步原语发出信号 &#xff08;例如Semaphore &#xff09;&#xff0c;并且测试将一…

网络编程---黏包

基于UDP协议的socket udp的server 不需要进行监听也不需要建立连接&#xff0c;在启动服务之后只能被动的等待客户端发送消息过来。 客户端发送消息的同时还会 自带地址信息&#xff0c;消息回复的时候 不仅需要发送消息 还需把对方的地址填上。 udp的client 不需要connect 因为…

CSS布局(二) 盒子模型属性

盒子模型的属性 宽高width/height 在CSS中&#xff0c;可以对任何块级元素设置显式高度。 如果指定高度大于显示内容所需高度&#xff0c;多余的高度会产生一个视觉效果&#xff0c;就好像有额外的内边距一样&#xff1b; 如果指定高度小于显示内容所需高度&#xff0c;取决于…

Extjs 下拉框

刚刚熟练了easyui控件的使用&#xff0c;又開始了如今的这个项目。这个项目是个半成品。前端使用的是Extjs控件&#xff0c;jsp中没有代码。就引用了非常多的js。。。于是乎有种不知所措了呀。。。 说实话特别的不想去看那些代码&#xff0c;第一是不熟悉&#xff0c;第二是太乱…

Java中的贷款模式(又名贷方承租人模式)

这篇文章是关于在Java中实现贷款模式的。 用例 在保存资源的代码与访问资源的代码之间实现分离&#xff0c;从而使访问代码无需管理资源。 当我们编写用于读取/写入文件或查询SQL / NOSQL数据库的代码时&#xff0c;上述用例适用。 在AOP的帮助下&#xff0c;肯定有API处理了此…

python亲密度_859. 亲密字符串(Python)

题目难度&#xff1a;★★☆☆☆类型&#xff1a;字符串给定两个由小写字母构成的字符串 A 和 B &#xff0c;只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果&#xff0c;就返回true &#xff1b;否则返回 false 。提示0 < A.length < 200000 < B.length &l…

开发电子商城1

1 从阿里云的镜像 下载centos 6.8 64位 https://mirrors.aliyun.com/centos/6.8/isos/x86_64/CentOS-6.8-x86_64-bin-DVD1.iso 2&#xff1a;用vm安装 选定basic service版本 3&#xff1a;将Centos的yum源更换为国内的阿里云源 http://www.centoscn.com/image-text/config/20…