直播app源码,如何提升用户登录验证的安全性?
直播app源码,如何提升用户登录验证的安全性?
目前开发的直播app源码很多,其中最基本的功能是用户登录,这是每一个系统基本上都有的功能,但一般系统对于这个功能的实现都比较简单,无法达到安全的目的。如何正确的对用户名密码进行验证,防止用户名、密码泄露,防止暴力破解,这是一个需要大家关心的问题。
直播app源码要完美的解决以上问题,需要了解加密、解密、数据安全、网络安全等相关知识,网上也有很多的解决方案。本文结合实际应用,给出一个例子,供大家参考。
2.1.1 采用安全HTTPS(SSL/TLS)协议
直播app源码采用安全HTTPS(SSL/TLS)协议,而不是普通的HTTP协议,这样前后端传输的内容就是加密后内容了,解决了明文传输的问题,可以很好地防止非法嗅探,
2.1.2 加强前后端安全处理
若有框架支持用户、密码的,则可直接用框架的用户登录、验证功能。
2.1.2.1 前端处理及传输
前端页面得到用户输入的用户名、密码、验证码后,采用Java script函数计算出密码的哈希值,然后调用后台方法进行用户验证,将用户名、密码哈希值、验证码作为后台方法的参数传入。
密码哈希值=哈希(密码明文+盐值(用户名+网站特有的字符串(如域名)))
2.1.2.1 后端验证方法
从数据库取出用户的密码哈希值和对应盐值
将盐值混入前端传入的密码哈希值,并且使用同样的哈希函数进行加密
比较上一步的结果和数据库储存的哈希值是否相同,如果相同那么密码正确,反之密码错误
2.1.2.1 后端数据库存储
数据库存储:用户名、盐值、密码哈希值
密码哈希值 = 哈希(前端传入的密码哈希值) = 哈希(密码明文+盐值(用户名+网站特有的字符串(如域名)))
盐值=随机值
盐值的一些注意事项:
每一用户应有不同的盐值(最常见的错误就是在多次哈希加密中使用相同的盐值或者太短的盐值)
用户创建账户或每次修改密码时都应该重新生成新的盐值进行加密
为了使攻击者无法构造包含所有可能盐值的查询表,盐值必须足够长。一个好的做法是使用和哈希函数输出的字符串等长的盐值比如SHA256算法的输出是256bits(32 bytes)那么盐值也至少应该是32个随机字节。
防止暴力破解,可在前端登录界面加入图片验证,登录时要求同时输入用户名、口令、验证码,这样就很好地防止了别人采用程序或机器人进行字典攻击、暴力攻击(通过采用尝试用户名、口令进行系统登录,从而获取用户信息)。
图片验证可以采用Google Kaptcha组件实现,在前端点击img组件时,调用后台Controller方法生成图像二进制流,直接更新图像内容。后台session中存储了正确的验证码字符串,与页面返回的tryCode比较。若一致跳转到新的页面,否则返回当前页面是,并显示错误信息。
前端关键示例代码如下所示:
<body>
<!-- 提示 -->
<h3 th:text="${info}"></h3>
<div>
<!-- 后面添加参数起到清除缓存作用 -->
<img alt="验证码" onclick="this.src='/defaultKaptcha?d='+new Date()*1" src="/defaultKaptcha" />
</div>
<form action="imgvrifyControllerDefaultKaptcha" >
<input type="text" name="tryCode" />
<input type="submit" value="提交" class="btn btn-success"></input>
</form>
</body>
后台验证码生成及验证关键代码:
/**
* 2、生成验证码
* @param httpServletRequest
* @param httpServletResponse
* @throws Exception
*/
@RequestMapping("/defaultKaptcha")
public void defaultKaptcha(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws Exception {
byte[] captchaChallengeAsJpeg = null;
ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream();
try {
// 生产验证码字符串并保存到session中
String createText = defaultKaptcha.createText();
httpServletRequest.getSession().setAttribute("rightCode", createText);
// 使用生产的验证码字符串返回一个BufferedImage对象并转为byte写入到byte数组中
BufferedImage challenge = defaultKaptcha.createImage(createText);
ImageIO.write(challenge, "jpg", jpegOutputStream);
} catch (IllegalArgumentException e) {
httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
// 定义response输出类型为image/jpeg类型,使用response输出流输出图片的byte数组
captchaChallengeAsJpeg = jpegOutputStream.toByteArray();
httpServletResponse.setHeader("Cache-Control", "no-store");
httpServletResponse.setHeader("Pragma", "no-cache");
httpServletResponse.setDateHeader("Expires", 0);
httpServletResponse.setContentType("image/jpeg");
ServletOutputStream responseOutputStream = httpServletResponse.getOutputStream();
responseOutputStream.write(captchaChallengeAsJpeg);
responseOutputStream.flush();
responseOutputStream.close();
}
/**
* 3、校对验证码
* @param httpServletRequest
* @param httpServletResponse
* @return
*/
@RequestMapping("/imgvrifyControllerDefaultKaptcha")
public ModelAndView imgvrifyControllerDefaultKaptcha(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
ModelAndView andView = new ModelAndView();
String rightCode = (String) httpServletRequest.getSession().getAttribute(