单点登录Redis存储Session及SessionId问题说明与集群实战-3

那现在我们就是要把sessionID的login请求,我们再看一下redis,回到我们的代码,我们现在不请求localhost:8080了,

我们要请求happymall.com,因为我们 已经把他配置了host,它会像我们读取的网站一样,一会请求tomcat1,一会请求tomcat2,

那我们把这个名字改一下,我们把redis清空一下

flushdb;

keys *

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第1张图片

这个时候我们请求打到tomcat2上,我们看一下writeLoginUser,进来,我们这个时候拿到的token是4B13k开头的,

这个token就是我们要存在redis里面的,并且domain一级域名下面的,然后放到response里面,addCookie,这个时候response

还没有返回,所以我们在浏览器里面,并且我们这个请求504超时了,504是nginx的超时时间,所以大家看到这个错误不要惊慌,

这是正常的,我们可以去修改nginx的超时时间,很简单的,因为我们现在主要是讲这个方法的调试,然后我们read一下我们进去,

读取的cookie都有两个,有什么,JSESSIONID,下面还有一个mmall_login_token

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第2张图片

但这个58A1是什么,是我们之前把这个断点,放过去,已经存到redis里的cookie,其实我们已经read过来了,我们可以看到

已经返回了

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第3张图片

继续删除loginToken,这里面也很简单,进去之后各种判断

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第4张图片

然后把它set到redis里面

keys *

4B13就在这里面了

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第5张图片

在这里要set一个,httpOnly,为true,那设置这个呢,是为了防止脚本攻击,这个属性规定,不允许通过脚本访问cookie,

在使用httpOnly这个cookie之后呢,断点就能够排除敏感信息,被发送给黑客的计算机,或者使用脚本的web断点的可能性,

那我们的代码这样设置之后,是无法通过脚本来获取这个信息的,同时浏览器也不会把cookie,发送给任何第三方,这样就保证了

信息的安全,当然他无法全面的保障我们断点的防止脚本攻击的安全,但是能提高一定的安全性,那是因为我们用的tomcat7,默认是

servlet3.0,属性可以直接设置,如果使用tomcat6的话,那这个属性要重新加用一下,tomcat6提供的servlet2.x,并不提供set方法,

那之前的做法呢,就是把这个属性设置在头里,然后我们再说一下,domain和path之间的关系,我们直接在这里加上注释,A.happymall

.com,第二个B.happymall.com,第三个A.happymall.com/test/cc,第四个A.happymall.com/test/dd,

第五个A.happymall.com/test,那现在对于这几个断点是这样的,

    //X:domain=".happymmall.com"
    //a:A.happymmall.com            cookie:domain=A.happymmall.com;path="/"
    //b:B.happymmall.com            cookie:domain=B.happymmall.com;path="/"
    //c:A.happymmall.com/test/cc    cookie:domain=A.happymmall.com;path="/test/cc"
    //d:A.happymmall.com/test/dd    cookie:domain=A.happymmall.com;path="/test/dd"
    //e:A.happymmall.com/test       cookie:domain=A.happymmall.com;path="/test"

A和B是二级域名,所以a拿不到b的cookie,因为他们是同级的,然后说c和d,能共享a的cookie,同样的c和d呢,也能共享e的cookie,

可以看一下test,e的cookie是这样的,所以c和d也能共享e的cookie,他们能读取到e的cookie,但是c拿不到d的,d拿不到c的,

c和d也拿不到b的,那他们之间的关系就是这样的,非常简单,也很容易理解,那我们就把domain设置成一级域名,path就设置

成根目录下,这样就比较通用,而且也比较简单,那我们就要抱着发展的思想来看这个问题
    private final static String COOKIE_DOMAIN = ".happymmall.com";
    private final static String COOKIE_NAME = "mmall_login_token";

    //X:domain=".happymmall.com"
    //a:A.happymmall.com            cookie:domain=A.happymmall.com;path="/"
    //b:B.happymmall.com            cookie:domain=B.happymmall.com;path="/"
    //c:A.happymmall.com/test/cc    cookie:domain=A.happymmall.com;path="/test/cc"
    //d:A.happymmall.com/test/dd    cookie:domain=A.happymmall.com;path="/test/dd"
    //e:A.happymmall.com/test       cookie:domain=A.happymmall.com;path="/test"

    public static void writeLoginToken(HttpServletResponse response,String token){
        Cookie ck = new Cookie(COOKIE_NAME,token);
        ck.setDomain(COOKIE_DOMAIN);
        ck.setPath("/");//代表设置在根目录
        ck.setHttpOnly(true);
        //单位是秒。
        //如果这个maxage不设置的话,cookie就不会写入硬盘,而是写在内存。只在当前页面有效。
        ck.setMaxAge(60 * 60 * 24 * 365);//如果是-1,代表永久
        log.info("write cookieName:{},cookieValue:{}",ck.getName(),ck.getValue());
        response.addCookie(ck);
    }
还记得我们之前设置host的时候,当时是有一个user.happymall.com的,我们简单说一下,那这个域名现在没有

启用,如果要启用的话呢,也是127.0.0.1,我们线上也没有配置,随着我们项目的不断演进,我们价格的演进,那么在后续

的时候,我们会把用户相关的,登陆注册,找回密码,忘记密码,重置密码,获取用户信息,包括管理员的权限判断,全部抽取

出来一个单独的服务,我们可以叫他用户中心,那么这个时候我们这个服务呢,以现在我们这种写法是可以通用的,例如我们

把cookie是放在一级域名下的,那我们在user.happymall.com里面,那我们的user.happymall.com,这里面所有关于登陆所有

session共享的,这些代码也都是OK的,因为它能够拿到这里面的cookie,那当然这是一个服务化的思想

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第6张图片

那现在是打到TOMCAT2上

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第7张图片

现在打到tomcat1上,我们再看一下cookie,JSESSIONID和刚才的tomcat2的不一样,但是mmall_login_token,8B63,

是一样的,那我们在读取用户信息的时候,就那mmall_login_token这个value,去redis里面查,可以查到了,这样无论是

tomcat1还是tomcat2,都能读到用户信息

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第8张图片

我们看一下redis里面

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第9张图片

那这个就是用户信息了,所以呢现在,我们这个cookie已经进入到一级域名下了,可以看到这个domain,

这个就是我们设置的maxage,我们设置的是一年,那继续来验证他,我们还有一个get_user_info方法,获取

用户信息,我们看看这个请求

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第10张图片

在代码里是POST请求,405 METHOD not allowed,这里我们要改成post,我们改成form,用户未登录,

用户无法获取当前信息

单点登录Redis存储Session及SessionId问题说明与集群实战-3_第11张图片

为什么会报这个错呢,很简单,看一下我们的代码,我们这里面还是在session里面去拿,那接下来我们就要改造他,

就是从cookie拿到mmal_login_token,然后从redis里面获取这个用户信息,同时还能演示我们的readCookie
    @RequestMapping(value = "get_user_info.do",method = RequestMethod.POST)
    @ResponseBody
    public ServerResponse getUserInfo(HttpServletRequest httpServletRequest){

        String loginToken = CookieUtil.readLoginToken(httpServletRequest);
        if(StringUtils.isEmpty(loginToken)){
            return ServerResponse.createByErrorMessage("用户未登录,无法获取当前用户的信息");
        }
        String userJsonStr = RedisShardedPoolUtil.get(loginToken);
        User user = JsonUtil.string2Obj(userJsonStr,User.class);

        if(user != null){
            return ServerResponse.createBySuccess(user);
        }
        return ServerResponse.createByErrorMessage("用户未登录,无法获取当前用户的信息");
    }

 

你可能感兴趣的:(单点登录Redis存储Session及SessionId问题说明与集群实战-3)