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

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

实现:

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. 洛谷 P1879 [USACO06NOV]玉米田Corn Fields 题解

    P1879 [USACO06NOV]玉米田Corn Fields 题目描述 Farmer John has purchased a lush new rectangular pasture compo ...

  2. 实现mysql的读写分离(mysql-proxy)____1(mysql的主从复制,基于gtid的主从复制,半同步复制,组复制)

    主从复制原理: 从库生成两个线程,一个I/O线程,一个SQL线程: i/o线程去请求主库 的binlog,并将得到的binlog日志写到relay log(中继日志) 文件中:主库会生成一个 log ...

  3. APP用户隐私协议

    告知用户 重视每个用户的的隐私,郑重承诺如下: 一.我们所收集的信息以及如何使用: 我们可能通过您的IP地址,地理位置信息,收集一些非个人隐私的统计资料,使我们能够进一步改善APP的服务.例如,当您浏 ...

  4. Git Bash设置代理

    从GitHub clone代码速度比较慢,设置代理,(假设端口是1080): git config --global https.proxy http://127.0.0.1:1080 git con ...

  5. SAS 指定LOG LIST输出

    LIBNAME S '.\'; PROC PRINTTO LOG='.\LOG\PRINT_LOG.LOG';RUN; DATA A;SET SASHELP.CLASS (FIRSTOBS=2 OBS ...

  6. 用Python实现一个简单的——人脸相似度对比

    近几年来,兴起了一股人工智能热潮,让人们见到了AI的能力和强大,比如图像识别,语音识别,机器翻译,无人驾驶等等.总体来说,AI的门槛还是比较高,不仅要学会使用框架实现,更重要的是,需要有一定的数学基础 ...

  7. mapdb的适用场景介绍

    对于大部分系统来说,mapdb并无太大价值,而且增加了成本.但是如果一级缓存巨大例如数以十GB级别,或占据了整个JVM的1/2以上,mapdb的价值就会体现出来.正如其官网介绍: MapDB prov ...

  8. ios 报错 Invalid row height provided by table delegate. Value must be at least 0.0, or UITableViewAutomaticDi......

    Invalid row height provided by table delegate. Value must be at least 0.0, or UITableViewAutomaticDi ...

  9. 二分查找时间复杂度、partition时间复杂度

    二分查找时间复杂度 partition时间复杂度 O(n) = O(n) + O(n/2) + O(n/4)+.... 然后用等比求和公式得出是O(2n),即O(n)

  10. vmware新加磁盘fdisk看不到的处理

    虚拟机硬盘空间不够了,做了lvm准备加块硬盘扩容,在vcenter控制台加了磁盘,结果操作系统里面fdisk -l看不到新加的硬盘,又不想重启怎么办,一条命令就可以搞定. # 注意中间有空格echo ...