会话

会话:浏览器从打开一个进程访问服务器到该浏览器关闭,我们称之为一个会话;

在浏览器和服务器交互期间,会不可避免地产生一些数据,而为了为每个用户保存其对应的数据,可使用两种技术:Cookie和Session;

Cookie

客户端技术,服务器会把用户的数据以cookie的形式写给每个客户端,当其再次访问时,就会携带相关的数据,这样使得服务器可以区分客户端处理数据;

Cookie在java中是通过javax.servlet.http.Cookie类创建的;其提供的方法有:

Cookie(String name , String value);//实例化Cookie对象,传入其名称和值
public String getNme();//取得Cookie的名称
public String getValue();//取得Cookie的值
public void setValue(String newValue);//设置Cookie的值
public void setMaxAge(int expiry);//设置Cookie最大的保存时间
public int getMaxAge();//获取Cookies的有效期,单位是秒
public void setPath(String uri);//设置cookie的有效路径,即在访问哪些路径时是自带Cookie的
public String getPath();//获取cookie的有效路径
public void setDomain(String pattern);//设置cookie的有效域
public String getDomain();//获取cookie的有效域

运用Cookie为每个浏览器都设置一个Cookie,并检查该请求是否已携带cookie:

import javax.servlet.http.Cookie;
PrintWriter out = resppnse.getWriter();
Cookie[] cookies = request.getCookies();
if (cookies != null){
for (int i = 0,i<cookies.length,i++){
Cookie cookie = cookies[i];
//找到所要核对的cooki名
if (cookie.getName().equals("lastaccesstime")){
Long lastaccesstime = Long.parseLong(cookie.getValue());
Date date = new Date(lastaccesstime);
out.write(date.toLocaleString());//将之前的cookie值转换为日期格式并输出
}
}
}else{
out.write("第一次访问本站");
}
Cookie cookie = new Cookie ("lastacccesstime",System.currentTimeMillis()+"");//无论是否第一次访问都为cookie设置当前的时间值
response.addCookie(cookie);//将新的cookie添加到response中并输出到客户端

一个Cookie只能标识一种信息,即一个web站点可以给同一个浏览器发送多个站点,一个浏览器也可以储存不同站点的Cookie标识;

如果不使用getMaxAge()将cookie保存到硬盘中的话,其信息是储存在内存中的,即关闭浏览器下次再登录是找不到原来的Cookie信息;删除Cookie时将其时间设置为0即相当于删除;

存储中文时需要使用URLEncoder类中的encode(String s,String enc)方法进行中文转码;

Cookie cookie = new Cookie("name",URLEncoder.encode("小兆","UTF-8"));

获取cookie中文时也需用URLEncoder类中的decode(String s ,String enc)进行解码;

URLDecoder.decode(cookies[i].getValue(),"UTF-8");

Session

服务器为每个用户浏览器都创建一个Session对象,用于保存用户数据,当用户去访问服务器其他程序时,其他程序可以通过用户的Session取出该用户的数据,为用户服务;

与Cookie的区别主要是:Cookie是写给浏览器,而Session是存在于服务器,当需要调用时,通过request对象的getSession方法得到Session对象;

getSession()方法会自动判断是否已存在session,如有,则调用,如没有,则创建;且一个session会有一个自己的ID以cookie的形式发送给浏览器,所以getSession()方法中应该存在创建sessionID且将其传给Cookie对象的程序过程;

判断是否已存在session:

HttpSession session = request.getSession();
session.setAttribute("data","小兆");//记得前面需将字符编码改为"UTF-8"
String sessionID= session.getID();
if(session.isNew()){
response.getWriter().print("创建成功,其session的id是:"+sessionID);
}else{
response.getWriter().print("已存在session,其session的id是:"+sessionID);
}

session对象默认30分钟没有使用,则服务器会自动销毁session,在web.xml文件中可以手工配置session的失效时间;

<session-config>
<session-timeout>12</session-tiomeout>
</session-config>

防止表单进行多次提交

在客户端防止:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
<head>
<title>Form表单</title>
<script type="text/javascript">
var isCommitted = false;//表单是否已经提交标识,默认为false
function dosubmit(){
if(isCommitted==false){
isCommitted = true;//提交表单后,将表单是否已经提交标识设置为true
return true;//返回true让表单正常提交
}else{
return false;//返回false那么表单将不提交
}
}
</script>
</head> <body>
<form action="${pageContext.request.contextPath}/servlet/DoFormServlet" onsubmit="return dosubmit()" method="post">
用户名:<input type="text" name="username">
<input type="submit" value="提交" id="submit">
</form>
</body>
</html>

可以通过运用JavaScript本身对其提交进行控制;

在服务端防止,在服务器上生成一个唯一标识码,称为Token令牌;在用户的session中保存Token并将其送往Form表单中,而form表单使用隐藏

域来储存Token,提交的时候一同提交到服务器中,此时服务器就根据session中的Token和提交上来的Token进行比较,如果一样,则提交成功,且在成功后将其Token信息在session中删除;如果发现表单或服务器中没携带Token或者其值不一致,则拒绝其表单提交;

生成唯一标识码并存储在session中,随后跳转到xxx.jsp页面:

String token = TokenProccessor.getInstance().makeToken();//创建令牌
request.getSession().setAttribute("token", token); //在服务器使用session保存token(令牌)
request.getRequestDispatcher("/xxx.jsp").forward(request, response);//跳转到form.jsp页面

编辑xxx.jsp页面,设置from表单,使用隐藏域来储存Token:

<form action="${pageContext.request.contextPath}/xxx" method="post">
<input type="hidden" name="token" value="${token}"/>
用户名:<input type="text" name="username">
<input type="submit" value="提交">
</form>

对比表单提交上来的以及服务器session对象储存的Token的值,判断是否处理请求:

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class DoFormServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { boolean b = isRepeatSubmit(request);//判断用户是否是重复提交
if(b==true){
System.out.println("请不要重复提交");
return;
}
request.getSession().removeAttribute("token");//移除session中的token
System.out.println("处理用户提交请求!!");
} /**
* 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
* @param request
* @return
* true 用户重复提交了表单
* false 用户没有重复提交表单
*/
private boolean isRepeatSubmit(HttpServletRequest request) {
String client_token = request.getParameter("token");
//1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
if(client_token==null){
return true;
}
//取出存储在Session中的token
String server_token = (String) request.getSession().getAttribute("token");
//2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
if(server_token==null){
return true;
}
//3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
if(!client_token.equals(server_token)){
return true;
} return false;
} public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
} }

关于前面的创建令牌方法大家可以自己实现即可,保证其唯一性;

java_第一年_JavaWeb(6)的更多相关文章

  1. java_第一年_JavaWeb(14)

    EL :EL表达式主要用于获取数据.执行运算.获取对象.调用java方法: 获取数据 语法:"${标识符}" 会调用pageContext.findAttribute方法,从pag ...

  2. java_第一年_JavaWeb(13)

    JSTL标签库——核心标签库 为了弥补html标签的不足,为了更加方便地在jsp页面中使用java逻辑代码,JSTL标签库因运而生,而其中的佼佼者,被恩宠最多的就是核心标签库了: 核心标签库从功能上可 ...

  3. java_第一年_JavaWeb(11)

    自定义标签:主要是用来移除JSP页面中的java代码. 先从一个简单的案例了解其怎么移除代码: 一个正常的jsp页面: <%@ page language="java" pa ...

  4. java_第一年_JavaWeb(15)

    Filter过滤器,Servlet API 中提供了一个Filter接口,用于实现用户在访问某个目标资源前对其进行拦截: 拦截原理:web服务器通过Filter接口调用doFilter方法,会传递一个 ...

  5. java_第一年_JavaWeb(12)

    SimpleTag标签 定义了五个方法:setJspContext.setJspBody.setParent和getParent以及最重要的doTag方法(完成了所有的业务逻辑): setJspCon ...

  6. java_第一年_JavaWeb(10)

    JavaWeb的两种开发模式 JSP+JavaBean框架:JavaBean负责封装数据.提供方法,JSP负责处理用户请求和显示数据:只能开发较为简单的业务: JSP+JavaBean+Servlet ...

  7. java_第一年_JavaWeb(9)

    JavaBean是一个遵循某种特定写法的Java类,有以下特点: 必需具有一个无参的构造函数 属性必需私有化 私有化的属性必需通过public类型的方法暴露给其它程序,其方法命名也有一定的规范 范例: ...

  8. java_第一年_JavaWeb(8)

    前面说到,JSP在运行时会被编译成Servlet源代码,通过_jspServlet方法处理请求,此时该方法会传递和提供9个与web开发相关的对象进行使用,开发人员在JSP页面通过对这些变量即可引用这9 ...

  9. java_第一年_JavaWeb(7)

    JSP执行过程 客户端发出请求访问JSP文件 JSP Container将要访问的JSP文件转译为Servlet的源代码(转译时期),并将其编译成.class文件(编译时期): 执行编译后的.clas ...

随机推荐

  1. js中的回调地狱 Callback to Hell

        本文重点:解决方式:1.promise  2. 拆解 function:将各步拆解为单个的 function  3. 通过 Generator 函数暂停执行的效果方式 4. 通过ES8的异步函 ...

  2. 自制悬浮框,愉快地查看栈顶 Activity

    接手陌生模块时,如何快速了解每个页面对应的类,以及它们之间的跳转逻辑.总不能在代码里一个一个地找startActivity()吧? 有时候,又想查看别人的 app 的页面组织(像淘宝.微信啊),总不能 ...

  3. service mesh学习规划

    istio go语言 谷歌开发 现有产品功能(每个功能具体支持哪些方式,优缺点) 服务注册发现 流量劫持 路由 负载均衡 熔断降级 流量控制(限流.流量分配) 重试机制 日志管理 支持的协议 监控(健 ...

  4. Google Capture The Flag 2018 (Quals) - Reverse - Beginner's Quest - Gatekeeper

    参考链接:https://ctftime.org/task/6264 题目 It's a media PC! All fully purchased through the online subscr ...

  5. c# 匿名委托

    using System; namespace AnonymousMethod { delegate void ArithmeticOperation(double operand1, double ...

  6. IDEA中项目引入独立包打包失败问题解决(找不到包)

    在terminal中执行以下命令:mvn install:install-file -DgroupId=ocx.GetRandom -DartifactId=GetRandom -Dversion=1 ...

  7. WiFi密码新攻击破解方法,黑客攻破只需10秒

    近日,中国知名黑客安全组织东方联盟研究人员透露了一种新的WiFi黑客技术,使黑客更容易破解大多数现代路由器的WiFi密码,并且攻破只需要10秒,速度非常快. 方法是利用由流行的密码破解工具Hashca ...

  8. Rabbit给单独的消息设置超时

    /** * 发送消息 * @param user */@RequestMapping(value = prefix+"/setRabbitMessage", method = Re ...

  9. 对webpack的初步研究6

    Plugins 插件是webpack 的支柱.webpack本身构建在您在webpack配置中使用的相同插件系统上! 它们也是这样做的目的别的,一个装载机无法做到的. Anatomy webpack  ...

  10. Java浏览器弹出下载框,多个文件导出压缩包

    项目里一直有这个功能,也一直没怎么注意,今天研究了一下 依据逻辑往下走: 首先是要下载的ajax的Java方法,只有返回值需要设定一下,其他的不用管: Map<String, Object> ...