第三章. 业务功能开发--用户登录安全退出

news2024/11/25 16:22:42

第三章. 业务功能开发--用户登录安全退出

1. 用户登录

需求:

用户在登录页面,输入用户名和密码,点击"登录"按钮或者回车,完成用户登录的功能.
	*用户名和密码不能为空
	*用户名或者密码错误,用户已过期,用户状态被锁定,ip受限 都不能登录成功
	*登录成功之后,所有业务页面显示当前用户的名称
	*实现10天记住密码
	*登录成功之后,跳转到业务主页面
	*登录失败,页面不跳转,提示信息
  1. 编写UserController

    通过前端传入的变量,读取数据库返回user对象,通过对象中的信息对上述的条件做出判断并对上述需求创合适的session

    然后将返回的信息放到object对象中返回出去,然后通过login.jsp中的信息做出判断,是否跳转到业务的控制台;

    package com.bjpowernode.crm.settings.web.controller;
    
    import com.bjpowernode.crm.commons.contants.Contants;
    import com.bjpowernode.crm.commons.domain.ReturnObject;
    import com.bjpowernode.crm.commons.utils.DateUtils;
    import com.bjpowernode.crm.settings.domain.User;
    import com.bjpowernode.crm.settings.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    @Controller
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        /**
         * url要和controller方法处理完请求之后,响应信息返回的页面的资源目录保持一致
         */
        @RequestMapping("/settings/qx/user/toLogin.do")
        public String toLogin(){
            //请求转发到登录页面
            return "settings/qx/user/login";
        }
    
        @RequestMapping("/settings/qx/user/login.do")
        public @ResponseBody Object login(String loginAct, String loginPwd, String isRemPwd,
                                          HttpServletRequest request, HttpServletResponse response, HttpSession session){
            //封装参数
            Map<String,Object> map=new HashMap<>();
            map.put("loginAct",loginAct);
            map.put("loginPwd",loginPwd);
            //调用service层方法,查询用户
            User user=userService.queryUserByLoginActAndPwd(map);
    
            //根据查询结果,生成响应信息
            ReturnObject returnObject=new ReturnObject();
            if(user==null){
                //登录失败,用户名或者密码错误
                returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
                returnObject.setMessage("用户名或者密码错误");
            }else{//进一步判断账号是否合法
                //user.getExpireTime()   //2019-10-20
                //        new Date()     //2020-09-10
                if(DateUtils.formateDateTime(new Date()).compareTo(user.getExpireTime())>0){
                    //登录失败,账号已过期
                    returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
                    returnObject.setMessage("账号已过期");
                }else if("0".equals(user.getLockState())){
                    //登录失败,状态被锁定
                    returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
                    returnObject.setMessage("状态被锁定");
                }else if(!user.getAllowIps().contains(request.getRemoteAddr())){
                    //登录失败,ip受限
                    returnObject.setCode(Contants.RETURN_OBJECT_CODE_FAIL);
                    returnObject.setMessage("ip受限");
                }else{
                    //登录成功
                    returnObject.setCode(Contants.RETURN_OBJECT_CODE_SUCCESS);
    
                    //把user保存到session中
                    session.setAttribute(Contants.SESSION_USER,user);
    
                    //如果需要记住密码,则往外写cookie
                    if("true".equals(isRemPwd)){
                        Cookie c1=new Cookie("loginAct",user.getLoginAct());
                        c1.setMaxAge(10*24*60*60);
                        response.addCookie(c1);
                        Cookie c2=new Cookie("loginPwd",user.getLoginPwd());
                        c2.setMaxAge(10*24*60*60);
                        response.addCookie(c2);
                    }else{
                        //把没有过期cookie删除
                        Cookie c1=new Cookie("loginAct","1");
                        c1.setMaxAge(0);
                        response.addCookie(c1);
                        Cookie c2=new Cookie("loginPwd","1");
                        c2.setMaxAge(0);
                        response.addCookie(c2);
                    }
                }
            }
    
            return returnObject;
        }
    
        @RequestMapping("/settings/qx/user/logout.do")
        public String logout(HttpServletResponse response,HttpSession session){
            //清空cookie
            Cookie c1=new Cookie("loginAct","1");
            c1.setMaxAge(0);
            response.addCookie(c1);
            Cookie c2=new Cookie("loginPwd","1");
            c2.setMaxAge(0);
            response.addCookie(c2);
            //销毁session
            session.invalidate();
            //跳转到首页
            return "redirect:/";//借助springmvc来重定向,response.sendRedirect("/crm/");
        }
    }
  2. 其中我的数据库中的user信息如下,一直报错,检查页面的返回数据得出,我的数据库密码和数据名称错了,下次注意。

  3. 在index.jsp 中更具返回的信息做出判断:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%
    	String basePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+request.getContextPath()+"/";
    %>
    <html>
    <head>
    	<base href="<%=basePath%>">
    <meta charset="UTF-8">
    <link href="jquery/bootstrap_3.3.0/css/bootstrap.min.css" type="text/css" rel="stylesheet" />
    <script type="text/javascript" src="jquery/jquery-1.11.1-min.js"></script>
    <script type="text/javascript" src="jquery/bootstrap_3.3.0/js/bootstrap.min.js"></script>
    <script type="text/javascript">
    	$(function () {
    		//给整个浏览器窗口添加键盘按下事件
    		$(window).keydown(function (e) {
    			//如果按的是回车键,则提交登录请求
    			if(e.keyCode==13){
    				$("#loginBtn").click();
    			}
    		});
    
    		//给"登录"按钮添加单击事件
    		$("#loginBtn").click(function () {
    			//收集参数
    			var loginAct=$.trim($("#loginAct").val());
    			var loginPwd=$.trim($("#loginPwd").val());
    			var isRemPwd=$("#isRemPwd").prop("checked");
    			//表单验证
    			if(loginAct==""){
    				alert("用户名不能为空");
    				return;
    			}
    			if(loginPwd==""){
    				alert("密码不能为空");
    				return;
    			}
    
    			//显示正在验证
    			$("#msg").text("正在努力验证....");
    			//发送请求
    			$.ajax({
    				url:'settings/qx/user/login.do',
    				data:{
    					loginAct:loginAct,
    					loginPwd:loginPwd,
    					isRemPwd:isRemPwd
    				},
    				type:'post',
    				dataType:'json',
    				success:function (data) {
    					if(data.code=="1"){
    						//跳转到业务主页面
    						window.location.href="workbench/index.do";
    					}else{
    						//提示信息
    						$("#msg").text(data.message);
    					}
    				   },
    				beforeSend:function () {//当ajax向后台发送请求之前,会自动执行本函数;
    					                    //该函数的返回值能够决定ajax是否真正向后台发送请求:
    									    //如果该函数返回true,则ajax会真正向后台发送请求;否则,如果该函数返回false,则ajax放弃向后台发送请求。
    					$("#msg").text("正在努力验证....");
    					return true;
    				}
    			});
    		});
    	});
    </script>
    </head>
    <body>
    	<div style="position: absolute; top: 0px; left: 0px; width: 60%;">
    		<img src="image/IMG_7114.JPG" style="width: 100%; height: 90%; position: relative; top: 50px;">
    	</div>
    	<div id="top" style="height: 50px; background-color: #3C3C3C; width: 100%;">
    		<div style="position: absolute; top: 5px; left: 0px; font-size: 30px; font-weight: 400; color: white; font-family: 'times new roman'">CRM &nbsp;<span style="font-size: 12px;">&copy;2019&nbsp;动力节点</span></div>
    	</div>
    	
    	<div style="position: absolute; top: 120px; right: 100px;width:450px;height:400px;border:1px solid #D5D5D5">
    		<div style="position: absolute; top: 0px; right: 60px;">
    			<div class="page-header">
    				<h1>登录</h1>
    			</div>
    			<form action="workbench/index.html" class="form-horizontal" role="form">
    				<div class="form-group form-group-lg">
    					<div style="width: 350px;">
    						<input class="form-control" id="loginAct" type="text" value="${cookie.loginAct.value}" placeholder="用户名">
    					</div>
    					<div style="width: 350px; position: relative;top: 20px;">
    						<input class="form-control" id="loginPwd" type="password" value="${cookie.loginPwd.value}" placeholder="密码">
    					</div>
    					<div class="checkbox"  style="position: relative;top: 30px; left: 10px;">
    						<label>
    							<c:if test="${not empty cookie.loginAct and not empty cookie.loginPwd}">
    								<input type="checkbox" id="isRemPwd" checked>
    							</c:if>
    							<c:if test="${empty cookie.loginAct or empty cookie.loginPwd}">
    								<input type="checkbox" id="isRemPwd">
    							</c:if>
    							 十天内免登录
    						</label>
    						&nbsp;&nbsp;
    						<span id="msg" style="color: red"></span>
    					</div>
    					<button type="button" id="loginBtn" class="btn btn-primary btn-lg btn-block"  style="width: 350px; position: relative;top: 45px;">登录</button>
    				</div>
    			</form>
    		</div>
    	</div>
    </body>
    </html>

2安全退出

需求如下:

用户在任意的业务页面,点击"退出"按钮,弹出确认退出的模态窗口;用户在确认退出的模态窗口,点击"确定"按钮,完成安全退出的功能.
	*安全退出,清空cookie,销毁session
	*退出完成之后,跳转到首页

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android Jetpack之Lifecycle的使用及源码分析

Lifecycle生命周期感知型组件可执行操作来响应另一个组件&#xff08;如 Activity 和 Fragment&#xff09;的生命周期状态的变化。这些组件有助于您编写出更有条理且往往更精简的代码&#xff0c;此类代码更易于维护。 尤其是在Activity和Fragment在已经默认支持LifeCycle的情…

【第五部分 | JS WebAPI】3:DOM 节点操作

目录 | 节点操作 1-1 概述 2-1 获取父节点 3-1 获取子节点&#xff08;获取所有子对象 不推荐&#xff09; 3-2 获取子节点&#xff08;获取所有子【元素节点】&#xff09; 3-3 获取首尾子节点 4-1 获取兄弟节点 5-1 动态创建、添加节点 5-2 案例&#xff1a;评论区 …

性能测试_JMeter_connection timed out :connect

jmeter报错:failed:connection timed out :connect/java.net.BindException: Address already in use: connect java.net.BindException: Address already in use: connectat java.net.DualStackPlainSocketImpl.connect0(Native Method)at java.net.DualStackPlainSocketImpl…

Linux系统上安装软件

安装jdk&#xff0c;安装tomcat&#xff0c;安装Mysql 四种安装方式&#xff1a; 安装jdk 1.去这个网站上下载linux版本的jdk Java Archive Downloads - Java SE 8 2.在虚拟机中的服务器终端中输入ifconfig&#xff08;注意不是ipconfig&#xff0c;而是ifconfig…

智慧机场解决方案-最新全套文件

智慧机场解决方案-最新全套文件一、建设背景二、建设思路三、建设方案四、获取 - 智慧机场全套最新解决方案合集一、建设背景 中国处在机场持续大规模建设过程中&#xff0c;政府也有意愿建设机场作为城市名片&#xff0c;经济持续增长会带来机场的持续建设&#xff1b;我国机…

螺旋模型的优点与缺点

螺旋模型&#xff1a; 特点&#xff1a; 螺旋模型在“瀑布模型”的每一个开发阶段前引入一个非常严格的风险识别、风险分析和风险控制&#xff0c;它把软件项目分解成一个个小项目。每个小项目都标识一个或多个主要风险&#xff0c;直到所有的主要风险因素都被确定 螺旋模型强…

Copilot:AI自动写代码,人工智能究竟还能取代什么?

Copilot&#xff1a;AI自动写代码&#xff0c;人工智能究竟还能取代什么&#xff1f; 前言 在AI绘画掀起一阵热潮之后&#xff0c;AI写代码又逐渐进入了我们的视野&#xff0c;似乎这一步我们还没想到就迅速到来了&#xff0c;难道说AI在取代画家之后&#xff0c;还要取代程序…

引擎入门 | Unity UI简介–第1部分(7)

本期我们继续为大家进行Unity UI简介&#xff08;第一部分&#xff09;的后续教程 本篇内容 14.放置标题图像 15.添加开始按钮 16.定位按钮 文章末尾可免费获取教程源代码 本篇Unity UI简介&#xff08;第一部分&#xff09;篇幅较长&#xff0c;分为十篇&#xff0c;本篇…

sqli-labs/Less-48

欢迎界面还是以sort为注入参数 接下来进行注入类型的判断 首先输入一下内容 sortrand() 多尝试几次 发现界面会发生变化 所以这一关属于数字型注入 然后我们选择使用报错注入 尝试输入一下内容 sortupdatexml(1,if(11,concat(0x7e,database(),0x7e),1),1)-- 回显如下 呦…

网络层 408真题 大题详解

1、【2009】 第一问有两种分配可能性&#xff0c;要想到位 记住&#x1f6a9; 路由器到互联网的路由相当于默认路由0/0 即目的地址0.0.0.0 子网掩码0.0.0.0 2、【2015】 注意&#x1f6a9;DHCP服务器不能转发信息 要观察到本图网络拓扑是同一个网络&#xff0c;在同一个网络中…

Linux系统man帮助一文通-尚文网络xUP楠哥

~~全文共1453字&#xff0c;阅读需约5分钟。 进Q群11372462&#xff0c;领取专属报名福利&#xff0c;包含云计算学习路线图代表性实战训练大厂云计算面试题资料! Linux帮助手册的常见章节 man是Manual的缩写&#xff0c;用来查看系统中命令和配置的帮助信息。Linux本地系统上…

Java#21(抽象与接口)

目录 一.抽象方法和抽象类 1.抽象方法: 2.抽象类: 3.注意: 二.接口 1.接口的定义 2.注意 3.接口中成员的特点 三.接口中的方法 1.JDK7以前: 接口中只能定义抽象方法2.JDK8: 接口中可以定义有方法体的方法(默认、静态) 3.JDK9: 接口中可以定义私有方法 一.抽象方法和…

【Call for papers】DSN-2023(CCF-B/截稿日期: 2022年12月7日)

文章目录1.会议信息2.时间节点3.论文主题On behalf of the Organizing Committee, we extend you a warm welcome to the 53rd Annual IEEE/IFIP International Conference on Dependable Systems and Networks (DSN 2023), organized by the University of Coimbra, Portugal.…

[ Linux ] 如何查看Linux系统版本

文章目录查看Linux内核Kernel的场景情况查看 Linux 版本的几种方式1、通过查看 redhat-release &#xff08;可查看小版本&#xff09;2、使用 lsb_release 命令 &#xff08;可查看小版本&#xff09;3、使用 hostnamectl 命令 &#xff08;只可查看大版本&#xff09;4、通过…

使用NNO区域进行色偏检测

想做图像的色偏检测&#xff0c;网上的资料全是同一套代码&#xff0c;就是2013年那个计算等价圆&#xff0c;然后直接用D-r>9 and K>0.6) or K>1.5&#xff0c;判断的代码&#xff08;相信大家都查到过了&#xff09; 但是色偏问题并不是这样简单的判断就可以的&…

一文掌握Python虚拟环境-提升你的开发效率

在真正开始Python代码编写、编译、运行、调试和开发项目之前&#xff0c;必须要了解下Python的虚拟环境的配置&#xff0c;熟悉使用后&#xff0c;会大大提升后续的开发效率&#xff0c;减少非代码原因导致的问题。virtualenv就是Python中的Virtual Environment-虚拟环境。本文…

C#界面里Form.HelpButton 属性的使用

C#界面里Form.HelpButton 属性的使用 Form.HelpButton 属性是获取或设置一个值,该值指示是否应在窗体的标题框中显示“帮助”按钮。 在一般的开发中,很少有人使用这个属性,因为程序比较简单,只要用户一上手就可以使用了。 如果界面比较复杂,或者说功能比较多,就需要使…

04【MyBatis的类型处理器】

四、MyBatis的类型处理器 4.1 typeAliases别名配置 类型别名是为 Java 类型设置一个短的名字&#xff0c;可以方便我们引用某个类。 我们仔细观察mapper.xml配置文件&#xff0c;会发现不管是入参&#xff08;paramterType&#xff09;还是出参&#xff08;ResultType&#…

大数据面试题(三):MapReduce核心高频面试题

文章目录 MapReduce核心高频面试题 一、ReduceTask工作机制 二、请描述mapReduce有几种排序及排序发生的阶段&#xff1f; 1、排序的分类 2、自定义排序WritableComparable 3、排序发生的阶段 三、请描述mapReduce中shuffle阶段的工作流程&#xff0c;如何优化shuffle阶…

Android App开发手机阅读中实现平滑翻书效果和卷曲翻书动画实战(附源码 简单易懂 可直接使用)

需要图片集和源码请点赞关注收藏后评论区留言~~~ 一、平滑翻书效果 与纸质书籍类似&#xff0c;手机上的电子书也有很多页&#xff0c;逐页浏览可采用翻页视图&#xff0c;然而翻页视图犹如一幅从左到右的绵长画卷&#xff0c;与现实生活中上下层叠的书籍并不相像&#xff0c;…