文档章节

关于跨域取cookie的问题

wangrikui
 wangrikui
发布于 2014/01/19 23:37
字数 1276
阅读 2725
收藏 3

比如说a.com和b.com两个不同的域,我在a.com中登录后,在b.com中就可以显示登录状态。

一、首先是在a.com中登录时,保存cookie,具体就不说了,先只把保存和读取cookie的工具类写下(这里要特别注意在保存cookie前对P3P头的设置,在后面会有具体说明):

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sun.misc.BASE64Encoder;

import cn.org.csip.jzzhaopin.model.Companyinfo;
import cn.org.csip.jzzhaopin.model.User;



public class MyCookieUtil {

    // 保存cookie时的cookieName
    private final static String cookieDomainName = Constants.COOKIE_NAME;

    // 加密cookie时的网站自定码
    private final static String webKey = "csip";

    // 设置cookie有效期是两小时,根据需要自定义
    private final static long cookieMaxAge = 60*60*2 ;

    // 保存Cookie到客户端--------------------------------------------------------------------------------------------------------
    // 传递进来的user对象中封装了在登陆时填写的用户名与密码
    public static void saveCookie(User user, HttpServletResponse response) {

        // cookie的有效期
        long validTime = System.currentTimeMillis() + (cookieMaxAge * 1000);

        // MD5加密用户详细信息

        String cookieValueWithMd5 = md5(user.getPwd());

        // 将要被保存的完整的Cookie值

        String cookieValue = user.getId()+":"+user.getUsercode() + ":" + cookieValueWithMd5
                + ":" + validTime + ":" + webKey+":"+"1";
        //在保存cookie前要设置P3P头,主要是在跨域取cookie的时候,防止IE浏览器的阻止cookie的读取
        response.setHeader("P3P","CP=\"CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM             NAV OTC NOI DSP COR\"");      

         // 开始保存Cookie
        Cookie cookie;
        try {
            cookie = new Cookie(cookieDomainName, URLEncoder.encode(cookieValue, "utf-8"));
            // 存两小时(这个值应该大于或等于validTime)
            cookie.setMaxAge(2*60*60);
            // cookie有效路径是网站根目录
            cookie.setPath("/");
            //设置跨域cookie
            //cookie.setDomain(".jzzhaopin.org.cn");

            // 向客户端写入
            response.addCookie(cookie);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }    
    }

//取cookie
    public String getCookies(String cookiename,HttpServletRequest request){
        Cookie[] cookie = request.getCookies();
        String cookievalue=null;
        if(cookie!=null){
             for(int i=0;i<cookie.length;i++){
                
                   if(cookie[i].getName().equals(cookiename))
                   {
                       try {
                        cookievalue=URLDecoder.decode(cookie[i].getValue(), "utf-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                       break;
                   }
              }
        }
        return cookievalue;
    }
    
    public Cookie clearCookie(String cookiename,HttpServletRequest request,HttpServletResponse response){
        Cookie[] cookie = request.getCookies();
        if(cookie!=null){
            for(int i=0;i<cookie.length;i++){
                 if(cookie[i].getName().equals(cookiename)){
                     cookie[i].setMaxAge(0);
                     cookie[i].setPath("/");
                     response.addCookie(cookie[i]);
                     return cookie[i];
                 }
            }
        }
        return null;
    }
    
    public static String md5(String message) {
        try {
            MessageDigest md = MessageDigest.getInstance("md5");
            byte[] result = md.digest(message.getBytes());

            BASE64Encoder encoder = new BASE64Encoder();
            return encoder.encode(result);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }
}
二、在b.com中读取cookie,我是通过jquery的getJSON方法跨域访问的cookie的。要页面加载时调用getJSON方法,去跨域读取a.com中的cookie。主要代码如下:

<script >
$(function(){
     $.getJSON('http://a.com/index/getCookieName.do?callback=?'+'&time='+new Date(),
    function(data){
              if(data[0]=="false"){
                 document.getElementById('welcome').innerHTML='';
                   
        }else if(data[0]=="cn.org.csip"){
                    document.getElementById('unlogin_l').style.display='none';
          document.getElementById('unlogin_r').style.display='none';
          document.getElementById('login_l').style.display='block';
            if(data[data.length-1]=='1'){
        datavalue='个人';
        document.getElementById('welcome').innerHTML='欢迎您:'+data[2]+','
    +'<a href="http://119.254.229.94:8980/jzzhaopin/ucenter/personalInfo.do">[进入'+datavalue+'中心]</a><a href="http://localhost:8080/jzzhaopin/login/logout.do">[注销]</a>';
            }
        if(data[data.length-1]=='2'){
            datavalue='单位';
            document.getElementById('welcome').innerHTML='欢迎您:'+data[2]+','
        +'<a href="http://119.254.229.94:8980/jzzhaopin/hr/companyinfo.do">[进入'+datavalue+'中心]</a><a href="http://localhost:8080/jzzhaopin/login/logout.do">[注销]</a>';
        }
    
    }
    });
});

</script>

其中,异步调用的aciton的代码为:

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import cn.org.csip.common.web.BaseAction;
import cn.org.csip.util.Constants;
import cn.org.csip.util.MyCookieUtil;

public class GetCookieNameAction extends BaseAction {

    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        response.setContentType("text/html;charset=utf-8");//此处必须设置该编码,否则中文到页面会出现乱码
        response.setHeader("P3P", "CP=\"IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA\"");
        //response.addHeader("P3P", "CP=\"IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA\"");
         String callback = request.getParameter("callback"); //获取回调函数的名字,此处一定不能少
        PrintWriter out=response.getWriter();
        //1.得到用户带过来的cookie
        MyCookieUtil myCookieUtil=new MyCookieUtil();
        String cookievalue=myCookieUtil.getCookies(Constants.COOKIE_NAME, request);
        if(cookievalue!=null){
            cookievalue=Constants.COOKIE_NAME+":"+cookievalue;
            String[] cookievalues=cookievalue.split("\\:");
            
            JSONArray json = JSONArray.fromObject(cookievalues);
            
            out.write(callback+"("+json.toString()+")");//此处注意返回的数据的格式,callback是一个函数,json.toString相当于是参数,所以要加个括号
            //out.write(Constants.COOKIE_NAME+":"+cookievalues[1]+";"+cookievalues[cookievalues.length-1]);
        }else{
            out.write(callback+"([\"false\"])");//此处是自定义json格式的数据
        }
        return null;
    }

}


需要注意的是:

用jquery的getJSON方法,事实上取得不是cookie,而是跨域取值。注意调的函数的json数据格式一定要严格按照action中写的那样,具体参看GetCookieNameAction.java;
url后面的callback是自定义的回调函数,后面的“?”就是一个具体的函数,只不过这里做了简化,可能是因为具体是什么函数无所谓,只要给个函数就行了。

IE浏览器,对cookie做了很严格的设置,即时按照上面的跨域方法,也是获取不到cookie的,解决方有两个:
一、更改本机的浏览器设置:更改隐私设置,级别调成最低即可;
二、在发送cookie的请求页面中(或者保存cookie的后台代码中)加入P3P头(只需要加入一次即可):针对java,在保存cookie之前,加上代码 response.setHeader("P3P","CP=\"CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR\"");

下面转载一篇关于P3P设置的文章,写的挺好,想具体了解下的可以看一下:http://blog.csdn.net/lovingprince/article/details/5984449



© 著作权归作者所有

wangrikui
粉丝 10
博文 31
码字总数 20614
作品 0
南京
后端工程师
私信 提问
加载中

评论(1)

水忘此处
水忘此处
GetCookieNameAction 在b.com 下,但是里面怎么直接调用了a.com 下的MyCookieUtil类。
就算MyCookieUtil是b.com 下的,那么这个时候得到的cookie是b.com下的,而不是a.com下的啊大哥~
EasyNVR如何实现跨域鉴权

EasyNVR提供简单的登录鉴权,客户端通过用户名密码登录成功后,服务端返回认证token的cookie, 后续的接口访问, 服务端从cookie读取token进行校验. 但是, 在与客户系统集成时, 往往需要在客户系...

xiejiashu
2017/11/28
0
0
淘淘商城系列——js跨域分析

通过上文的学习,我有理由相信大家都实现了用户登录,登录的时候我们把token写入到了cookie当中,登录成功后,我们查看cookie的信息,如下图所示,发现是有token信息的。 我们回到登录页面,...

yerenyuan_pku
2017/06/15
0
0
前后端分离 | 关于登录状态那些事

背景 登录是一个网站最基础的功能。有人说它很简单,其实不然,登录逻辑很简单,但涉及知识点比较多,如: 密码加密、cookie、session、token、JWT等。 我们看一下传统的做法,前后端统一在一...

小忽悠
2018/10/12
0
0
使用cookie实现大屏数据“千人千面”

使用cookie实现大屏数据“千人千面” 细心的用户注意到,在产品的数据配置面板中,如果选择API作为数据源,会有两个小的勾选项,分别是“由服务器发起请求(HTTP 代理)”和“需要 cookie (...

央九
2018/05/18
0
0
Discuz!NT3.1 用户登录Cookie中密码加密方式探索

今天朋友找我,说有一个论坛和网站,一年多前网站的制作者未曾实现Dicuz!NT同步功能,问题遗留至今。两年前我曾利用 DiscuzTookit开发包,实现网站和论坛登录同步、注册同步、修改资料同步、...

李朝强
2014/08/19
389
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
126
7
SpringBoot中 集成 redisTemplate 对 Redis 的操作(二)

SpringBoot中 集成 redisTemplate 对 Redis 的操作(二) List 类型的操作 1、 向列表左侧添加数据 Long leftPush = redisTemplate.opsForList().leftPush("name", name); 2、 向列表右......

TcWong
今天
18
0
排序––快速排序(二)

根据排序––快速排序(一)的描述,现准备写一个快速排序的主体框架: 1、首先需要设置一个枢轴元素即setPivot(int i); 2、然后需要与枢轴元素进行比较即int comparePivot(int j); 3、最后...

FAT_mt
昨天
4
0
mysql概览

学习知识,首先要有一个总体的认识。以下为mysql概览 1-架构图 2-Detail csdn |简书 | 头条 | SegmentFault 思否 | 掘金 | 开源中国 |

程序员深夜写bug
昨天
10
0
golang微服务框架go-micro 入门笔记2.2 micro工具之微应用利器micro web

micro web micro 功能非常强大,本文将详细阐述micro web 命令行的功能 阅读本文前你可能需要进行如下知识储备 golang分布式微服务框架go-micro 入门笔记1:搭建go-micro环境, golang微服务框架...

非正式解决方案
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部