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

用户登录

在各大信息管理系统中,登录功能是必不可少的,他的作用就是验证用户的身份,判断用户是否是本站的会员,只有会员才能访问当前系统

登录的实现步骤:

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>

</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 = ?

登录失败效果

登录成功效果

用户注销

用户注销功能的主要作用是保护用户的账户安全,在用户点击安全退出的时候,我们需要将本次会话相关的session信息删除

删除的方式有下面两种:
1.删除当前登录的用户信息
存在问题:本次会话的其他信息还是保存在内存中,没有及时清理

@WebServlet("/logout")

public class LogoutServlet extends HttpServlet {

private IEmployeeService service = new EmployeeServiceImpl();

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

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项目:多条件过滤

前往叩丁狼官网获取更多技术视频

看完了吗?看完了就赶快行动起来,打开你的编辑器,开始编译登陆界面实现登陆注册吧!

手把手教你做JavaWeb项目:登录模块的更多相关文章

  1. UWP Jenkins + NuGet + MSBuild 手把手教你做自动UWP Build 和 App store包

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

  2. 转载:手把手教你做iOS推送

    手把手教你做iOS推送 http://www.cocoachina.com/industry/20130321/5862.html

  3. R数据分析:跟随top期刊手把手教你做一个临床预测模型

    临床预测模型也是大家比较感兴趣的,今天就带着大家看一篇临床预测模型的文章,并且用一个例子给大家过一遍做法. 这篇文章来自护理领域顶级期刊的文章,文章名在下面 Ballesta-Castillejos ...

  4. 手把手教你做个人 app

    我们都知道,开发一个app很大程度依赖服务端:服务端提供接口数据,然后我们展示:另外,开发一个app,还需要美工协助切图.没了接口,没了美工,app似乎只能做成单机版或工具类app,真的是这样的吗?先 ...

  5. 手把手教你做echarts图表系列之组织结构图

    在实际项目中使用echarts越来越多了,今天从一个组织结构图开始,手把手教大家开发echarts图表. 公司里的组织结构图如下: 可以参考echarts入门教程:http://echarts.bai ...

  6. iOS不得姐项目--登录模块的布局,设置文本框占位文字颜色,自定义内部控件竖直排列的按钮

    一.登录模块的布局 将一整部分切割成若干部分来完成,如图分成了三部分来完成 设置顶部状态栏为白色的方法 二.设置文本框占位文字颜色 <1>方法一与方法二实现原理是同一种,都是通过设置pla ...

  7. 手把手教你做个AR涂涂乐

    前段时间公司有一个AR涂涂乐的项目,虽然之前接触过AR也写过小Demo,但是没有完整开发过AR项目.不过经过1个多星期的学习,现在已经把项目相关的技术都学会了,在此向互联网上那些乐于分享的程序员前辈们 ...

  8. 手把手教你做爬虫---基于NodeJs

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

  9. 小KING教你做android项目(一)

    写在项目开始之前: 最近关于android的视频教程,入门的书籍也已经有很多了,例如我的入门就是看了mars的视频教程.但是这么一圈学习下来,觉得真正快速提高的,不是在看视频,而是在实际工作中动手做项 ...

随机推荐

  1. Kafka的基本概念

    Kafka的前身是由LinkedIn开源的一款产品,2011年初开始开源,加入了 Apache 基金会,2012年从 Apache Incubator 毕业变成了 Apache 顶级开源项目. Top ...

  2. ssl 原理简介

    要想弄明白SSL认证原理,首先要对CA有有所了解,它在SSL认证过程中有非常重要的作用.说白了,CA就是一个组织,专门为网络服务器颁发证书的,国际知名的CA机构有VeriSign.Symantec,国 ...

  3. 「NOIP2016」换教室

    传送门 Description 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 $ 2n $ 节课程安排在 $ n $ 个时间段上.在第 $ i ...

  4. C++ STL(标准模板库)的学习了解

    C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量.链表.队列.栈. C++ 标准模板库的核心包括以 ...

  5. 经典算法(三) 单链表 反转 & 是否相交/成环 & 求交点 等

    参考文章: 判断链表是否相交:http://treemanfm.iteye.com/blog/2044196 一.单链表反转 链表节点 public class Node { private int ...

  6. nohup: 无法运行命令"java": 没有那个文件或目录

    问题 在一个Linux服务器上有shell 脚本如下: nohup java -jar test.jar >> ./nohup.out 2>&1 & 直接执行脚本 s ...

  7. Linux虚拟机:发布WebService接口出现异常,无法访问接口

    Linux虚拟机:发布WebService接口出现异常,无法访问接口 今天在部署WebService工程的时候遇到的问题: 在Linux虚拟机上部署一个tomcat同时在tomcat下放置2个工程,其 ...

  8. http 请求方式解析

    表单中<form></form>, 如果使用method="get"方式提交,则不会指定请求体编码方式.默认请求参数使用?拼接到url之后.如:http:/ ...

  9. Linux内核链表——看这一篇文章就够了

    本文从最基本的内核链表出发,引出初始化INIT_LIST_HEAD函数,然后介绍list_add,通过改变链表位置的问题引出list_for_each函数,然后为了获取容器结构地址,引出offseto ...

  10. vscode配置python之settings.json 智能提示

    vscode编写Python的智能提示,搞了好久,参考了各种网上配置,如下,备份方便自己查找. { "workbench.iconTheme": "material-ic ...