登录与注册功能(简单版)(3)登录时使用Cookie增加记住我功能

目录

1、实现分析

2、步骤

1)新建login.jsp

2)修改LoginServlet:

3)启动访问:

3、安全性考虑

4、最佳实践思路

1)选择安全的认证机制

2)强化会话管理

3)安全地存储用户凭证

4)使用HTTPS

5)安全的Cookie管理

6)定期审查和更新

7)提醒用户


1、实现分析

需求:勾选“记住我” ,下次访问登陆页面自动填充用户名密码。

怎样自动填充用户名和密码?

记住我功能要实现的效果:用户把浏览器关闭过几天再来访问也能自动填充,所以需要将登陆信息存入一个可以长久保存、并且能够在浏览器关闭、重启后依然有效的地方:使用Cookie。

将用户名和密码写入Cookie中,并持久化存储Cookie,下次访问浏览器,发送请求时会自动携带Cookie。

在页面获取Cookie数据后,设置到用户名和密码框中。

什么时候写入Cookie?
登录成功且用户在登录页面勾选了记住我的复选框。

流程分析:

  • 前端需要在发送请求和数据的时候,多携带一个用户是否勾选记住我的数据。
  • LoginServlet获取到数据后,调用Service完成用户名和密码的验证。
  • 登录成功,并且用户在前端勾选了记住我,需要向Cookie中写入用户名和密码的数据,并设置Cookie的有效期。
  • 将数据响应给前端,这时后端返回给前端的Cookie数据就已经存储好了。
  • 在页面获取Cookie中的数据,并把数据设置到登录页面的用户名和密码框中。

2、步骤

1)新建login.jsp

在webapp中新建;使用JSP相较于HTML在此功能更有优势)

JSP(Java Server Pages):Java 服务端页面。是一种动态的网页技术,其中既可以定义 HTML、JS、CSS等静态内容,也可以定义 Java代码的动态内容,也就是 JSP = HTML + Java。

作用:简化开发,避免了在Servlet中直接输出HTML标签(频繁地用response.getWriter().write()方法输出)。

JSP页面最终会被Web服务器(Tomcat)转换为Servlet,然后由Java Web容器执行。

使用Servlet进行逻辑代码开发、使用JSP进行数据展示,已过时。

更多的是使用 HTML +  Ajax:

使用Servlet进行后端逻辑代码开发、使用HTML进行数据展示:HTML是静态页面,怎么进行动态数据展示呢?这就是 Ajax 的作用了。

为了可以在页面获取Cookie中的数据,使用JSP+EL表达式:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>

<body>
    <form action="login" method="post" id="form">
        <p>用户名:<input id="username" name="username" value="${cookie.username.value}" type="text"></p>
        <p>密码:<input id="password" name="password" value="${cookie.password.value}" type="password"></p>
        <p>记住我<input id="remember" name="remember" value="1" type="checkbox"></p>
        <input type="submit" class="button" value="登录">
    </form>
</div>
</body>
</html>

EL表达式:

主要作用是获取数据。其实就是从域对象中获取数据,然后将数据展示在页面上。

${cookie.key.value}   

key:存储在Cookie中的键的名称

获取用户名的值: ${cookie.username.value}

获取密码的值:${cookie.password.value}

JavaWeb中有四大域对象:

page:当前页面有效
request:当前请求有效,包括请求转发forward
session:当前会话有效
application:当前应用有效

EL表达式获取数据会依次从这4个域(作用范围从小到大)中寻找,直到找到为止。

记住我复选框:在用户提交表单时,前端将checkbox的状态(选中或未选中,这里将选中的值设为1,用于之后的判断)作为请求的一部分发送到后端。

2)修改LoginServlet:

获取复选框的值并在登录成功后进行设置Cookie

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //获取参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
 //获取复选框数据
        String remember=request.getParameter("remember");

        //使用MyBatis查询数据表,如果用传来的参数能查到User对象,则成功登录
        //MyBatis的使用步骤
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.selectUser(username, password);
        sqlSession.close();

        //进行响应
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer=response.getWriter();
        if (user!=null){
            //登录成功
 //判断用户是否勾选记住我,字符串写前面是为了避免出现空指针异常
            if("1".equals(remember)){
            //勾选了记住我 :发送Cookie
            //1. 创建Cookie对象
            Cookie c_username=new Cookie("username",username);
            Cookie c_password=new Cookie("password",password);
               // 设置Cookie的有效期
            c_username.setMaxAge(60*60*24*7); //一周
            c_password.setMaxAge(60*60*24*7);
            //2. 发送
            response.addCookie(c_username);
            response.addCookie(c_password);
            }
            //将登陆成功后的user对象存储到session
            HttpSession session=request.getSession();
            session.setAttribute("user",user);

            request.setAttribute("username",username);
            request.getRequestDispatcher("/SuccessServlet").forward(request,response);
        }else {
            writer.write("登录失败");
        }
    }

}

3)启动访问:

只有用户名和密码输入正确且勾选了remeber的复选框,在响应头中才可以看到Cookie数据:

​​​​​​​​​​​​​​登录成功并勾选了记住我后,后端返回给前端的Cookie数据就已经存储好了,接下来就需要在页面获取Cookie中的数据,并把数据设置到登录页面的用户名和密码框中。

关闭浏览器,重新访问登录页面:用户和密码已经被填充。

3、安全性考虑

虽然确实可以将用户名和密码(或任何其他数据)写入Cookie中,并通过设置Cookie的持久化属性使其在浏览器中保存一段时间,但是不推荐将敏感信息如用户名和密码存储在Cookie中。

原因:

  1. 安全性问题:Cookie是在客户端(即用户的浏览器)上存储的。这意味着任何能够访问用户计算机的人或恶意软件都可以读取这些Cookie。因此,将用户名和密码存储在Cookie中会使这些信息面临被窃取的风险。

  2. 明文存储:默认情况下,Cookie是以明文形式存储的。即使通过某种方式加密了用户名和密码,但如果加密密钥也存储在客户端或易于访问的地方,那么这些信息仍然可能面临被解密的风险。

  3. 会话劫持:如果攻击者能够获取到包含用户名和密码的Cookie,他们可以伪造请求,冒充合法用户访问应用,导致会话劫持。​​​​​​​

更好的做法

使用安全的认证机制,如OAuth、OpenID Connect或简单的用户名/密码认证结合安全的会话管理。在用户名/密码认证中,当用户成功登录后,服务器应该生成一个唯一的会话ID,并将其存储在Cookie中。这个会话ID应该与服务器上的会话数据相关联,而不是直接包含用户名和密码。其中可以包含用户的认证状态和其他必要信息。这样,即使敏感信息不在客户端存储,也可以通过会话ID识别已登录的用户。即使Cookie被窃取,攻击者也无法直接获取到用户的敏感信息。同时,使用HTTPS来加密浏览器和服务器之间的通信也是至关重要的,即使Cookie被窃取,攻击者也无法轻易解密其中的内容,从而确保Cookie在传输过程中的安全性。

总之,虽然技术上可以将用户名和密码写入Cookie并持久化存储,但出于安全考虑,应该采用更安全的会话管理方法来处理用户的认证状态。

4、最佳实践思路

安全地使用“记住我”功能的最佳实践涉及到多个方面,包括认证机制的选择、会话管理的安全性以及用户凭证的存储和处理。以下是一些关键的最佳实践:

1)选择安全的认证机制

  • OAuth/OpenID Connect:使用OAuth或OpenID Connect等第三方认证服务。这些服务提供了更高级别的安全性,并且通常已经解决了许多常见的安全问题。

  • 用户名/密码认证:如果使用传统的用户名/密码认证,确保密码策略足够强大,包括要求密码长度、复杂度,并定期提示用户更改密码。

2)强化会话管理

  • 会话ID:使用不可预测的、足够长的会话ID,并且不要将用户ID或其他敏感信息直接编码在会话ID中。

  • 会话有效期:限制“记住我”功能的会话有效期,避免长期会话带来的潜在风险。定期要求用户重新登录,特别是在敏感操作之前。

  • 会话固定:实施会话固定策略,以防止会话劫持。当用户登录时,生成一个新的会话ID,并立即使之前的会话ID失效。

  • 会话注销:提供明确的会话注销机制,并确保在用户登出时,所有相关的会话数据都被正确清除。

3)安全地存储用户凭证

  • 加密存储:用户凭证(如密码)应始终以加密形式存储,并且使用强加密算法和安全的密钥管理策略。

  • 避免明文存储:绝不要以明文形式存储或传输用户凭证,包括在“记住我”功能的实现中。

4)使用HTTPS

  • 全程加密:确保整个应用都使用HTTPS,包括登录页面、认证过程和所有后续的用户交互。这可以防止中间人攻击和数据泄露。

5)安全的Cookie管理

  • HttpOnly和Secure标志:为存储会话信息的Cookie设置HttpOnly和Secure标志,防止跨站脚本攻击(XSS)和未加密的传输。

  • 避免在Cookie中存储敏感信息:不要在Cookie中直接存储用户的敏感信息,如密码或加密密钥。

6)定期审查和更新

  • 安全检查:定期检查是否有潜在的安全漏洞或风险。

  • 更新和补丁:及时应用安全更新和补丁,以修复已知的安全问题。

7)提醒用户

  • 不要在公共计算机或不受信任的网络环境中使用此功能。

  • 定期查看和修改他们的登录信息。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数字化战略失配企业现状,可惜了!

尽管大部分的企业领导者已经意识到数字化转型对于企业革新业务模式、提升运营效率、抢占市场先机的关键作用&#xff0c;但是&#xff0c;认知上的转变并不等同于成功的实践。在实际操作中&#xff0c;往往出现战略与企业现状不符的现象&#xff0c;这无疑会使得所有的努力付诸…

矩形总面积(第十四届蓝桥杯JavaB组省赛真题)

测试用例范围比较大&#xff0c;所以全部用long类型&#xff0c;如果用int类型只能通过60%&#xff0c;建议在内存和运行时间允许的情况下&#xff0c;比赛题都用long。 重点在于计算相交的面积&#xff0c;这里找的两个相交点是左上角&#xff08;m1,n1&#xff09;和右下角&a…

公司系统中了.rmallox勒索病毒如何恢复数据?

早晨上班时刻&#xff1a; 当阳光逐渐洒满大地&#xff0c;城市的喧嚣开始涌动&#xff0c;某公司的员工们纷纷踏入办公大楼&#xff0c;准备开始新的一天的工作。他们像往常一样打开电脑&#xff0c;准备接收邮件、查看日程、浏览项目进展。 病毒悄然发作&#xff1a; 就在员…

万亿参数GPU!算力提升30倍!英伟达新核弹B200重磅发布!

关注文章底部的公众号,获取每日AI资讯 前沿 3月18日-21日期间,英伟达在美国圣何塞召开GTC大会。创始人黄仁勋也在GTC大会上,做了一场长达两小时的开幕演讲,展示了其在AI芯片、机器人、汽车等领域的最新研发成果和技术进展,号称让全世界用上AI。 全球头号人工智能领域开发…

加解密、签名、验签、数字签名、数字证书

说明&#xff1a;本文属于学习笔记&#xff0c;借鉴了很多经典网文&#xff0c;已记不清出处&#xff0c;如有侵权&#xff0c;请告知。 前言&#xff1a; 嵌入式开发时&#xff0c;绕不开数据安全问题。最近又在做OTA升级相关工作&#xff0c;因此&#xff0c;借此机会学习了加…

MySQL 索引:索引为什么使用 B+树?

Hash 索引不支持顺序和范围查询&#xff1b; 二叉查找树(BST)&#xff1a;解决了排序的问题&#xff0c;极端情况下可能会退化成线性链表&#xff0c;查询效率急剧下降&#xff1b; 平衡二叉树(AVL) &#xff1a;通过旋转解决了平衡的问题&#xff0c;但是旋转操作效率太低&am…

从点云创建 DSM:网格化和可视化实用指南

今天我将向您展示如何从点云创建数字表面模型&#xff08;DSM&#xff09;。首先&#xff0c;我们将尝试了解 DSM 是什么&#xff0c;然后我们将进入讨论的更实际部分。 什么是 DSM&#xff1f; DSM 是一个描述表面及其表面所有内容的模型。现在&#xff0c;为了更清楚地了解…

分布式异步任务框架celery

Celery介绍 github地址&#xff1a;GitHub - celery/celery: Distributed Task Queue (development branch) 文档地址&#xff1a;Celery - Distributed Task Queue — Celery 5.3.6 documentation 1.1 Celery是什么 celery时一个灵活且可靠的处理大量消息的分布式系统&…

hcip复习总结1

OSI----------- 定义了数据的产生标准 。 7 层 应用 ------- 表示 会话 传输 -----Telnet - 23 ssh---22 http---80 https-443 TCP ---- 传输控制卋议。是一种面向连接的可靠的传输卋议。 UDP---- 用户数据报卋议。是一种非面向连接的丌可靠传输卋议。 保证可靠性&…

鸿蒙开发-UI-动画-页面间动画

鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 鸿蒙开发-UI-图形-图片 鸿蒙开发-UI-图形-绘制几何图形 鸿蒙开发-UI-图形-绘制自定义图形 鸿蒙开发-UI-图形-页面内动画 鸿蒙开发-UI-图形-组件内转场动画 鸿蒙开发-UI-图形-弹簧曲线动画 文章目录 前言 一、放大缩…

Springboot+vue的医疗挂号管理系统+数据库+报告+免费远程调试

效果介绍: Springbootvue的医疗挂号管理系统&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 本文设计了一个基于Springbootvue的前后端分离的医疗挂号管理系统&#xff0c;采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;con…

Kubernetes集群搭建 kubernetes集群安装

Kubeadm kubeadm 是 Kubernetes 社区提供的集群构建工具&#xff0c;它能够以最佳实践的方式部署一个最小化的可用 Kubernetes 集群。 但是 kubeadm 在设计上并未安装网络解决方案&#xff0c;所以需要用户自行安装第三方符合 CNI 的网络解决方案&#xff0c;如 flanal&#…

7个方便快速使用的Tkinter控件源码分享,赶快收藏

文章目录 7个快速使用的Tkinter控件源码分享1. 按钮 Button2. 开关 Checkbutton3. 显示文本 Label4. 带名称、数值显示的划动条5. 带标签的复选框6. 带名称的输入框7. 带名称的微调框7个快速使用的Tkinter控件源码分享 tkinter 是一个简单入手,但是功能十分强大的GUI编程库,学…

阶乘的强悍溢出技能

【题目描述】 输入n&#xff0c;计算S&#xff1d;1&#xff01;&#xff0b;2&#xff01;&#xff0b;3&#xff01;&#xff0b;…&#xff0b;n&#xff01;的末6位&#xff08;不含前导0&#xff09;。&#xff0c;n&#xff01;表示 前n个正整数之积。 【样例输入】 …

[python]bar_chart_race设置日期格式

1、设置日期标签的时间格式 # 设置日期格式&#xff0c;默认为%Y-%m-%dbcr.bar_chart_race(df, covid19_horiz.gif, period_fmt%b %-d, %Y) 2、更改日期标签为数值 # 设置日期标签为数值bcr.bar_chart_race(df.reset_index(dropTrue), covid19_horiz.gif, interpolate_period…

基于springboot+vue的中山社区医疗综合服务平台

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

第二十八天-ES6标准入门和Flex布局

目录 1.ES6标准入门 2.ES6与JavaScript关系 3.ES6常用新特性 1.变量与常量 1.let三大特性 2.常量三大特征 2.解构赋值 1.数组解构赋值 2.对象解构赋值 3.字符串解构赋值 3.函数与箭头函数 1.函数 2.箭头函数 4.JS的面向对象编程 5.模块化 export使用 import使用…

QT界面制作

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);this->setWindowFlag(Qt::FramelessWindowHint);//接收动图QMovie *mv new QMovie(":/pictrue/th.gif…

二分查找算法(2)

852.山脉数组的峰顶索引 一、题目描述 即下标 i 前的所有元素都升序、后的所有元素都降序&#xff0c; i 是最大值 OJ题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09; 二、思路解析 三、代码 class Solution { public:int peakIndexInMountainArray(vector<in…

算法打卡day11

今日任务&#xff1a; 1&#xff09;239. 滑动窗口最大值 2&#xff09;347.前 K 个高频元素 239. 滑动窗口最大值 题目链接&#xff1a;239. 滑动窗口最大值 - 力扣&#xff08;LeetCode&#xff09; 给定一个数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移…