1.背景介绍

团队开发的项目,前端基于Bootstrap+AngularJS,后端Spring MVC以RESTful接口给前端调用。开发和部署都是前后端分离。项目简单部署图如下,因为后台同时采用微服务的方式,所以后台不止3个,画图示意。终极方案是采用Docker,在前端和后台调用中间添加一层:API Gateway。

因为考虑到和其他系统集成的可能性,所以在登录这一块使用了Token来做登录,认证服务器负责生成Token和验证Token。因为客户需要提高系统的安全性,需要在登录页添加一个验证码。但是因为项目是基于前后端分离的,所以添加验证码的功能还是有一些不一样。

2.Session解决方案

有经验的开发者第一反应就是之前验证码怎么添加的,现在在这里也是同样的道理,为什么不一样呢?因为前后端分离,系统登录使用的是Token,后台不再设置Session了。后台必须保证当前用户输入的验证码是用户开始请求页面时候的验证码,必须保证验证码的唯一性。举个例子:

A用户看到的验证码是:ABC;B用户看到的验证码是:DEF。后台存储了ABC和DEF这2个验证码,如果不限定A用户输入的验证码是ABC,那么当A用户碰巧输入DEF,然后用户名和密码也是正确的话,A用户也是可以登录系统的。

在早期可以使用Session系统中,后台返回验证码信息同时写入一个session,有一个SessionID的字段和当前这个验证码对应。所以当用户输入用户名、密码和验证码的时候,浏览器自动把存有session信息的cookie发送到服务器,服务器基于Session可以判断当前这个验证码确实是A用户应该要输入的。

缺点:为了考虑到后续和其他系统集成,同时后台部署是多台服务器,采用的API网关。已经使用了Token,如果为了验证码这个功能,引入Session,有点得不偿失。

3.无Session解决方案

不能使用Session,那只能考虑无Session的方案。要同时获取验证码和验证码对应的一个id值。作为前端的我,第一反应是通过AngularJS中的$http请求去获取。但是后台验证码是直接读取图片返回二进制流格式给到前端,所以不能额外返回一个ID字段。后端开发同事就说,那在Response Header里面返回一个id的字段,和验证码的值相关联起来。到现在听起来一切都很顺利。前端代码如下:

//控制器层代码
$scope.getCaptcha = function () {
loginService.getCaptcha().success(function (response, status, headers) {
$scope.id = headers().id; if (response.size > 0) {
$scope.verificationImage = window.URL.createObjectURL(response);
} else {
toastr.error("获取验证码失败:" + response.message);
} }).error(function (response) {
console.log(response);
});
}
//服务层代码
getCaptcha: function () {
return $http({
method: "GET",
responseType: "blob",
url: AppConfig.userServerUrl + "/user/Captcha/request"
});
},

前端AngularJS代码无法获取header头部额外字段,能获取的字段如下:

在stackoverflow上搜索一番,解决办法是后台需要设置允许前端浏览器能获取header头部里面的字段。后台同事修改之后,response header里面信息如下图所示:

同域和跨越解决办法:How to read response headers in angularjs?

4.IE9下的bug

以为大功告成,然后在IE9浏览器上测试一下,发现无法加载到验证码,而且控制台报错误。折腾半天,发现IE9不支持window.URL.createObjectURL();,而且AngularJS发送请求加载二进制流文件就报错。

为了支持IE9,目前解决方法是让后台不返回二进制流文件,而是返回base64编码的字符串,这样IE9也是支持的。

5.可选一种方式

和之前同事交流一番,同事提出了一个可选的方案。因为我们在请求验证码的时候有2个内容,一个是验证码id,一个验证码图片。其实验证码id可以在前端使用随机数生成一个,然后前端把这个id传入后台,后台根据这个id,然后加一些特殊字符,拼接之后一个唯一字符,同时生成一个图片,这个唯一字符和这个验证码图片关联起来,然后将图片返回base64编码内容返回到前端。这种可以不需要前端发送Ajax请求,直接在图片上使用ng-src

<img ng-src="http://www.example.com?uid=1001cmss" >

参考文档

浅谈COOKIE和SESSION关系和区别等

Angular企业级开发(9)-前后端分离之后添加验证码的更多相关文章

  1. 无需CORS,用nginx解决跨域问题,轻松实现低代码开发的前后端分离

    近年来,前后端分离已经成为中大型软件项目开发的最佳实践. 在技术层面,前后端分离指在同一个Web系统中,前端服务器和后端服务器采用不同的技术栈,利用标准的WebAPI完成协同工作.这种前后端分离的&q ...

  2. CoreCRM 开发实录 —— 前后端分离的重构

    虽然2月初就回来了,可 CoreCRM 一直到5月才开始恢复开发,期间是各种生活中的意外和不方便. 1. 为什么要重构 首先是一件很值得高兴的事情:CoreCRM 有了第一位 contributor! ...

  3. Django系列---开发三 前后端分离

    数据交互接口规范REST,全称 Representational State Transfer,意为"表现层状态转化". django的第三方拓展--django-rest-fra ...

  4. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 十四 ║ VUE 计划书 & 我的前后端开发简史

    ---新内容开始--- 番外 大家周一好呀,又是元气满满的一个周一呀!感谢大家在周一这个着急改Bug的黄金时期,抽出时间来看我的博文哈哈哈,时间真快,已经到第十四篇博文了,也很顺顺(跌跌)利利 (撞撞 ...

  5. 手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(一) - 介绍

    项目简介 novel 是一套基于时下最新 Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离的学习型小说项目,配备详细的项目教程手把手教你从零开始开发上线一个生产级别的 J ...

  6. 基于Vue的前后端分离项目实践

    一.为什么需要前后端分离 1.1什么是前后端分离  前后端分离这个词刚在毕业(15年)那会就听说过,但是直到17年前都没有接触过前后端分离的项目.怎么理解前后端分离?直观的感觉就是前后端分开去做,即功 ...

  7. 前后端分离(手)-- 使用mock.js(好样的)

    ## 前言: 本篇博文昨天七夕写的,一天下来被虐得体无完肤,苦逼的单身狗只能学习,对!我爱学习,关掉朋友圈,并写了一篇博文发泄发泄.这次写mock.js的使用,能使前后端分离,分离,分离,重要的是说三 ...

  8. 《Spring Boot 入门及前后端分离项目实践》系列介绍

    课程计划 课程地址点这里 本课程是一个 Spring Boot 技术栈的实战类课程,课程共分为 3 个部分,前面两个部分为基础环境准备和相关概念介绍,第三个部分是 Spring Boot 项目实践开发 ...

  9. SSM框架中的前后端分离

    认识前后端分离 在传统的web应用开发中,大多数的程序员会将浏览器作为前后端的分界线.将浏览器中为用户进行页面展示的部分称之为前端,而将运行在服务器,为前端提供业务逻辑和数据准备的所有代码统称为后端. ...

随机推荐

  1. js记录重复字母的个数

    var str = "hello"; var obj = {}; for (var i = 0; i < str.length; i++) { var v = str.cha ...

  2. Spring Boot启动过程(一)

    之前在排查一个线上问题时,不得不仔细跑了很多遍Spring Boot的代码,于是整理一下,我用的是1.4.3.RELEASE. 首先,普通的入口,这没什么好说的,我就随便贴贴代码了: SpringAp ...

  3. .NET 通用高扩展性的细粒度权限管理架构(webApi/Mvc)

    一. 权限场景分析: 1. 系统具有角色概念, 部门概念, 且都具有相应不同的权限 2. 用户具有多个角色, 多个部门等关系, 并且能给单个用户指派独有的权限 3. 具有细粒度权限控制到资源的RBAC ...

  4. PLSQL语法深入浅出

    一:PLSQL概览:PLSQL 是Oracle公司在SQL基础上进行扩展而成的一种过程语言.PLSQL提供了典型的高级语言特 性,包括封装,例外处理机制,信息隐藏,面向对象等:并把新的编程思想带到了数 ...

  5. Java如何判断字符串中包含有全角,半角符号

    首先介绍下全角跟半角之间的区别: 在计算机屏幕上,一个汉字要占两个英文字符的位置,人们把一个英文字符所占的位置称为"半角",相对地把一个汉字所占的位置称为"全角" ...

  6. Eclipse 报java.lang.UnsupportedClassVersionError: ("yourclass") bad major version at offset=6

    报这个错误是指你的jar包或者class 的被编译的jdk版本比当前runtime的jdk版本高. 解决问题 1)如果是jar包,重新用jdk 1.6编译你的jar 包 2)如果是java文件或者项目 ...

  7. form表单的两种提交方式,submit和button的用法

    1.当输入用户名和密码为空的时候,需要判断.这时候就用到了校验用户名和密码,这个需要在jsp的前端页面写:有两种方法,一种是用submit提交.一种是用button提交.方法一: 在jsp的前端页面的 ...

  8. 苹果手机上开发微信公众号(wap)遇到的问题解决方法

    1.样式 苹果 手机会自行强制css样式,比如input会变得面目全非,你可以加上input{-webkit-appearance: none;}恢复原貌! 2.jquery的live错误,苹果手机上 ...

  9. Ninject之旅之十二:Ninject在Windows Form程序上的应用(附程序下载)

    摘要: 下面的几篇文章介绍如何使用Ninject创建不同类型的应用系统.包括: Windows Form应用系统 ASP.NET MVC应用系统 ASP.NET Web Form应用系统 尽管对于不同 ...

  10. 一个普通底层.NET程序员关于职场瓶颈期的思考,辗转自我提升/跳槽/转行之间

    徒有工龄,没技术没学历没平台没家底,工作几年,无车无房无存款还前景不明. 时常有身边的亲友问怎么学开发怎么转互联网,说起IT行业都说工资高,动辄月薪上万动辄年薪几十万. 再看看自己,我可能是假的程序员 ...