手把手教你做javaweb项目:登录模块

     2022-04-01     816

关键词:

现如今,无论是客户端还是移动端,无论是电动登陆还是社交平台登陆,无处不在的“登陆”。那么你知道怎么制作吗?今天就为你娓娓道来:

用户登录
在各大信息管理系统中,登录功能是必不可少的,他的作用就是验证用户的身份,判断用户是否是本站的会员,只有会员才能访问当前系统
登录的实现步骤:
1.用户填写账号和密码,提交到后台
2.后台获取到账号和密码后,将其发送到数据库中进行查询
3.查询结果如果为null,说明用户填写的账号或者密码有误,应该回到登录页面并提示用户重新输入
4.查询结果如果不为null,说明用户填写的账号和密码正确,将对应的账户信息共享到session中(在后面的请求,我们还需要继续使用当前登录的用户信息),然后跳转到网站的主页面
按照上面的步骤,我们使用下面的代码完成了相应功能
1.登录页面
<form class="form-horizontal" action="/login" method="post">
<div class="form-group">
<label for="inputEmail3" class="col-sm-3 control-label">用户名</label>
<div class="col-sm-9">
<input type="text" name="name" class="form-control" id="inputEmail3">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label">密???码</label>
<div class="col-sm-9">
<input type="password" name="password" class="form-control" id="inputPassword3">
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-3 control-label"></label>
<div class="col-sm-9">
<button type="submit" class="btn btn-default">登录</button>br/></div>
</div>
页面中存在很多布局相关的代码,大家可以直接略过,重点看表单元素相关的标签即可
LoginServlet
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
private IEmployeeService service = new EmployeeServiceImpl();

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String name = req.getParameter("name");
    String password = req.getParameter("password");
    Employee currentUser = service.login(name, password);
    if(currentUser==null){
        //登录失败
        req.setAttribute("errorMsg","亲,账户或者密码错误");
        req.getRequestDispatcher("/login.jsp").forward(req,resp);
        return;
    }else{
        //登录成功
        req.getSession().setAttribute("USER_IN_SESSION",currentUser);
        resp.sendRedirect("/employee");
        return;
    }

SQL:
SELECT * FROM employee WHERE name = ? AND password = ?
登录失败效果

技术图片

登录成功效果

技术图片br/>用户注销
用户注销功能的主要作用是保护用户的账户安全,在用户点击安全退出的时候,我们需要将本次会话相关的session信息删除
删除的方式有下面两种:
1.删除当前登录的用户信息
存在问题:本次会话的其他信息还是保存在内存中,没有及时清理
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
private IEmployeeService service = new EmployeeServiceImpl();
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/login.jsp");
}
}
2.销毁整个session(推荐)
@WebServlet("/logout")
br/>req.getSession().removeAttribute("USER_IN_SESSION");
resp.sendRedirect("/login.jsp");
}
}
2.销毁整个session(推荐)
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
private IEmployeeService service = new EmployeeServiceImpl();
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().invalidate();
resp.sendRedirect("/login.jsp");
}
}
验证码
验证码是每个系统必不可少的功能,主要是用来防止系统被恶意***,如果没有这个功能,那么我们的系统就如同没有上锁的家门一样,小偷随时能进来干坏事
所以我们来看看,在登录的时候如何使用验证码,其他模块如果要使用,原理一样

技术图片

1.首先,需要在登录页面显示出验证码的图片,用户可以根据图片中的文字进行填写
2.同时,在生成验证码的时候,我们需要将正确的验证码保存到session中,供后面校验使用
3.用户填写好验证码后,提交表单,后台校验
注:生成验证码的代码不是我们这里的重点,以后如果需要,在网上一搜一箩筐,所以我就不贴出来了
校验代码
//校验验证码是否正确
String randomcode_in_session = (String) req.getSession().getAttribute("RANDOMCODE_IN_SESSION");
String randomCode = req.getParameter("randomCode");
if (!StringUtils.isNullOrEmpty(randomCode) && !StringUtils.isNullOrEmpty(randomcode_in_session)) {
if (!randomCode.equals(randomcode_in_session)) {
Cookie nameCookie = new Cookie("name", name);
Cookie passwordCookie = new Cookie("password", password);
resp.addCookie(nameCookie);
resp.addCookie(passwordCookie);
handleError(req, resp, "亲,验证码错误");
return;
}
} else {
handleError(req, resp, "验证码不能为空或者验证码已失效");
return;
}

private void handleError(HttpServletRequest req, HttpServletResponse resp, String errorMsg)
throws ServletException, IOException
req.getSession().setAttribute("errorMsg", errorMsg);
resp.sendRedirect("/login.jsp");
}
当用户没填写验证码或者session中的验证码失效,都应该给出错误提示
如果用户填写的和session中保存的验证码不匹配,给出错误提示
如此,当验证码不正确的时候,我们就不会继续做登录校验,必须等用户填写出正确的验证码才可以,而这一点,机器是无法做到的
记住账号
该功能的目的主要是想在用户一次登录之后,下次可以不再重新填写账号,增加用户体验
想要实现该功能,我们需要在后台将用户的账号信息进行共享
但是,我们应该使用什么来完成共享呢?
来,想想我们的需求,我今天早上十点第一次登陆系统,使用完之后,关闭浏览器,下午还需要登陆几次,明天后天...
那么我想在这种需求下都可以不再填写账号
在这样的需求下,我相信大家能够想到一个答案---cookie
Cookie是将数据保存在浏览器中,而且,我们可以设置保存的时间,可以在关闭浏览器之后仍然能够继续使用
所以,Cookie就是我们在这个需求中的最佳解决方案
在登录的业务逻辑添加如下代码,将账号相关信息保存到使用Cookie进行保存
//记住我
String rememberMe = req.getParameter("rememberMe");
if (!StringUtils.isNullOrEmpty(rememberMe)) {
//将用户信息保存到Cookie中
Cookie nameCookie = new Cookie("name", name);
nameCookie.setMaxAge(60 60 24);

        Cookie rememberMeCookie = new Cookie("rememberMe", rememberMe);
        rememberMeCookie.setMaxAge(60 * 60 * 24);
        resp.addCookie(nameCookie);
        resp.addCookie(rememberMeCookie);
    } else {
        //将用户信息从Cookie中移除
        Cookie[] cookies = req.getCookies();
        for (Cookie cookie : cookies) {
            if ("name".equals(cookie.getName())  || "rememberMe".equals(cookie.getName())) {
                cookie.setMaxAge(0);
                resp.addCookie(cookie);
            }
        }
    }

然后,在登录页面获取到Cookie中的数据即可
<div class="form-group">
<label for="inputEmail3" class="col-sm-3 control-label">用户名</label>
<div class="col-sm-9">
<input type="text" name="name" class="form-control" id="inputEmail3"
value="${cookie.name.value}">
</div>
</div>

<label>
<input type="checkbox" name="rememberMe"
${empty cookie.rememberMe.value?"":"checked=‘checked‘"}> Remember me
</label>
当选择了记住我后,登录错误回到登录页面,此时能够自动获取到上次的账号信息

技术图片
登录检查
在用户没有登录的情况下,不允许访问系统中除登录以外的其他模块,如果访问,应该直接回到登录页面
在javaweb中,这个问题的最佳解决方案就是使用过滤器(Filter)
过滤器:能够在访问到达目标资源之前对请求做预处理,在响应离开之前对响应做预处理
在我们这个需求中,是需要对请求做预处理的,检查用户在请求当前资源之前,是否已经登录
实现步骤:
1.定义过滤器:CheckLoginFilter
public class CheckLoginFilter implements Filter {
private List<String> needCheckURIs;

public void init(FilterConfig filterConfig) throws ServletException {
    //获取到需要校验的资源名称(如果需要校验的资源较多,可以配置不需要校验的资源)
    String needCheckURI = filterConfig.getInitParameter("needCheckURI");
    String[] split = needCheckURI.split(",");
    //将所有的资源名存放到集合中,待后面进行校验
    needCheckURIs = Arrays.asList(split);
}

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 
            throws IOException, ServletException {

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse resp = (HttpServletResponse) response;
    //获取当前请求的资源名
    String requestURI = req.getRequestURI();
    //如果当前请求的资源是不需要校验的,直接放行
    if(!needCheckURIs.contains(requestURI)){
        filterChain.doFilter(req, resp);
        return;
    }
    //如果需要校验,判断用户是否登录,是,则放行,反之回到登录页面
    Object currentUser = req.getSession().getAttribute("USER_IN_SESSION");
    if (currentUser == null) {
        resp.sendRedirect("/login.jsp");
        return;
    }
    filterChain.doFilter(req, resp);
}

public void destroy() {

}

}
2.将过滤器交给Tomcat服务器管理
<!--登录检查过滤器-->
<filter>
<filter-name>CheckLoginFilter</filter-name>
<filter-class>cn.wolfcode.javaweb.web.filter.CheckLoginFilter</filter-class>
<init-param>
<param-name>needCheckURI</param-name>
<param-value>/employee,/department</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CheckLoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
有了该过滤器,用户就不能再没有登录的时候,直接访问相关资源了,做到了一个基本的安全控制
生成系统账户
当系统启动后,我们需要在用户表中存在一个最起码的管理员账户,这样,用户才能登录进来来管理整个系统
那么,如何实现在启动服务器的时候,完成这个需求呢?
其实解决方案很多,大家也都应该能想到
1.Servlet
Servlet默认情况下是在第一次访问的时候执行初始化操作
但是也可以调整到启动服务器的时候,<load-on-startup>0</load-on-startup>
初始化Servlet的时候,会执行当前Servlet的init方法
所以,我们完全在该方法中来完成这个需求
2.Filter
过滤器的初始化就是在启动服务器的时候
和Servlet一样,初始化的时候会执行Filter的init方法
所以,也可以在Filter的init方法中完成该需求
3.Listener
前面学习过WEB中的监听器,知道他能够对作用域(创建/销毁)和作用域中的属性(添加/删除/修改)进行监听
我们的需求是,在启动服务器的时候创建默认账户
而在启动服务器的时候,application作用域对象会在这个时候创建
综上,我们可以创建一个application作用对象监听器,在创建该对象的时候,完成默认账户的创建
上面三种方式都能完成我们的需求,但最终从责任分离原则方面考虑,我们应该选择使用监听器,实现如下
创建监听器
public class SystemManagerCreaterListener implements ServletContextListener {
private IEmployeeService service = new EmployeeServiceImpl();
public void contextInitialized(ServletContextEvent servletContextEvent) {
//查询系统默认账户是否存在,如果不存在,创建一个默认账户
Employee manager = service.selectSystemManager();
if(manager==null){
manager = new Employee();
manager.setName("admin");
manager.setPassword("1");
manager.setAdmin(true);
service.save(manager);
}
}

public void contextDestroyed(ServletContextEvent servletContextEvent) {

}

}
注册监听器
<listener>
<listener-class>cn.wolfcode.javaweb.web.listener.SystemManagerCreaterListener</listener-class>
</listener>
如此,在启动服务器的时候,先会到员工表中查询,是否存在默认的管理员账户。
点击查看JavaWeb系列的其它文章
手把手教你做JavaWeb项目:项目需求分析
手把手教你做JavaWeb项目:前台界面
手把手教你做JavaWeb项目:多条件过滤
前往叩丁狼官网获取更多技术视频
看完了吗?看完了就赶快行动起来,打开你的编辑器,开始编译登陆界面实现登陆注册吧!




手把手教你做项目多线程篇——基础知识详解(代码片段)

...特性锁互斥锁信号量送点资源导读随着暑假的推进,手把手教你做项目前边的准备也差不多了后续的项目也渐渐要开始了但是正式发出来可能要等一段时间前后端都是我一个人确实有点费力(毕竟我也是菜鸡),... 查看详情

手把手教你做产品经理

课程目录:001说在前面的话002我的互联网观003与你息息相关的未来004我们应该如何让学习更有效率005我们应该如何让学习更有效率006真实产品案例-案例学习重点与项目背景007真实产品案例-大讨论与项目定调008真实产品案例-用户... 查看详情

手把手教你做项目web框架flask篇——基础用法详解(代码片段)

目录导读为什么用flask安装flask启动flaskflask里name的用处转换器和变量规则重定向设置错误页面json数据读取cookie和session对cookie的获取和删除session操作request的使用蓝图开发必备视图资源分享导读今天接着为暑假的项目做准备,... 查看详情

520到了,教你做个javaweb表白墙小项目

目录1.配置Maven项目1.1创建Maven项目1.2引入相关依赖1.3项目总结构2.约定前后端交互接口3.服务端代码3.1 创建Message类3.2创建工具类3.3添加信息类(AddMessage)3.4查询信息类(MessageList)4.前端代码5.创建数据库6.部署项... 查看详情

手把手教你做蓝牙小车

第1节选择Arduino开发板1.1Arduino是什么对Arduino,官方有一堆解释。作为一个软件程序猿,在我眼里,Arduino是学习“可怕硬件”的一个便捷通道。它把复杂的硬件名称,属性给我们隐藏起来,只需要一些简单的软件知识,就可以学... 查看详情

手把手教你做一个缓存工具(代码片段)

日常开发中,某些数据接口即使优化到极致,都难免还会存在计算量巨大导致响应过慢,多数情况单独做一个统计表用于存放这些处理后的数据用于读取,或者接入redis/memcache存数据,就是说单次响应本身是可以接受较慢一些的... 查看详情

万字干货:手把手教你做需求管理

通过这篇文章,总结自己在工作实践中需求管理的方法论——普拉姆方法。总结这个方法论的特点是,用最轻量化的投入,与他人协作,并管理需求,推动需求上线。这套方法论组合了项目管理、敏捷开发的知识,希望能对大家... 查看详情

手把手教你做安豆计算器-计算器界面布局

第3节计算器界面布局现在起,我们就开始正式开发“计算器”应用。这一节,我们将完成计算器的界面布局,让它初具计算器的模样。计算器界面是通过布局文件定义的。它位于项目的reslayoutactivity_main.xml文件中。这个布局文件... 查看详情

手把手教你做一个python+matplotlib的炫酷的数据可视化动图(代码片段)

1.效果图 2.注意:上述资料是虚拟的,为了学习制作动图,构建的。仅供学习,不是真实数据,请别误传。当自己需要对真实数据进行可视化时,可进行适当修改。 3.代码:#第1步:导出模块,固定importpandasaspdimportmatplotli... 查看详情

阿里测试工程师,手把手教你做测试用例设计!

设计APP测试案例的时候,需要有清晰的测试思路,对要测试什么,按照什么顺序测试,覆盖哪些需求做到心中有数。测试用例编写者不仅要掌握软件测试的技术和流程,而且要对被测软件的设计、功能规格说... 查看详情

手把手教你把git子模块更新到主项目(代码片段)

本文以skywalking-rocketbot-ui子模块合并到skywalking为例,手把手教你如何把Git子模块更新到主项目中去。首先,把fork的skywalking项目克隆到本地:OneMoreMINGW64/d/code$gitclonehttps://github.com/heihaozi/skywalking.gitskywalkingCl 查看详情

手把手教你做爬虫---基于nodejs

前言:趁着北京今儿天气格外的蓝,我觉得我得干点什么,于是乎,卷起袖子,整理一下最近做爬虫的那些事儿。目标:爬取北京大学软件与微电子学院的所有新闻,并将内容及图片存储到本地。设计思路:经过对北京大学软件... 查看详情

手把手教你把git子模块更新到主项目

...术A本文以skywalking-rocketbot-ui子模块合并到skywalking为例,手把手教你如何把Git子模块更新到主项目中去。首先,把fork的skywalking项目克隆到本地:进入skywalking目录,设置用户名和邮箱:指定将与复刻同步的远程上游仓库:查看一... 查看详情

uwpjenkins+nuget+msbuild手把手教你做自动uwpbuild和appstore包

背景项目上需要做UWP的自动安装包,在以前的公司接触的是TFS来做自动build。公司要求用Jenkins 来做,别笑话我,之前还真不晓得这个东西。会的同学请看一下支持错误,不会的同学请先自行脑补,我们一步一步的来。首先我... 查看详情

axure-手把手教你做汉化

 ?我们默认下载的AXURE是英文版的,对于英文能力不足或者不习惯英文界面的,那必须使用汉化手段,网上也有很多朋友已经为大家做好了汉化文件,这里介绍一下如何自己做AXURE的汉化。如何开始汉化如何开始汉化,只需要... 查看详情

手把手教你写!javaweb开发实例大全源码

什么是ServiceMesh作为ServiceMesh技术探索和实践的先行者,全球第一个真正的ServiceMesh项目Linkerd负责人、Buoyant公司创始人兼CEOWilliamMorgan第一次完整地阐述了ServiceMesh。按照WilliamMorgan的定义,ServiceMesh是一个致力于解决服务间... 查看详情

手把手教你做音乐播放器音乐列表的存储(上)

第5节播放列表的存取关于播放列表的存取需要三个组件的协同配合,MusicListActivity:让用户选择多首或一首音乐,将用户的选择项,传递给MusicService;MusicService:接收到添加列表的请求后,把数据交给PlayListContentProvider,进行存... 查看详情

手把手教你做一个电子相册(代码片段)

1、概述首先介绍下什么是HaaS:2020年9月17日,在云栖大会上阿里云IoT团队正式发布了HaaS(HardwareasaServie)。HaaS是一种物联网设备云端一体开发框架,它的目的是通过数量收敛的硬件积木(比如主控板:... 查看详情