20191126 Java Web之单系统登录知识点

1、前言

在工作中登录功能十分常见,自己也接触了不少,如常见的单系统账密登录,以及无需输入账密的扫码登录,以及通过第三方登录实现快速注册登录,还有微信小程序的授权登录。这里要做个总结的话也是挺多东西可以写的。

虽然工作中没有单点登录的需求,但它也是Java WEB中很重要的一块知识,于是觉得很有必要了解一下。而要学懂单点登录,单系统登录是基础。

文中也不由自主的介绍Java Web相关的一些知识。因此可能全文读下来会抓不到重点,也是我写作技巧不够还需努力提升。我也尽力去整理下章节顺序和小标题了,让文章整体更加清晰。

涉及到的知识点有:

  • http协议
  • session
  • cookie
  • 会话机制
  • tomcat
  • redis
  • 跨域问题
  • 浏览器的同源策略

2、单系统登录

单系统登录的实现是单点登录实现的基础,而且也涉及到了不少知识点,因此理解单系统是十分有必要的。

2.1、B/S架构

web应用采用的是B/S架构,以http协议为通信协议。而http属于无状态的请求-响应模式,即浏览器向服务器发起一次请求,服务器会给予一次响应。并且对于服务器而言,每次的请求都是全新的,即跟之前的请求没有任何关联。

2.2、web资源需要被保护

但是对于一些资源的访问,如私密的信息,如我的相册、我的好友列表等,需要被保护,即需要验证身份才能进行访问,而登录操作就是身份验证的一种方式。

那么我们可以规定:只有通过登录验证的,才能去访问自己的相册图片。可是这样并不安全,因为登录操作实质上是发起一次http请求,而访问图片实质上也是发起一次http请求。也就是说,通过上面规定的简单的流程控制,并不能实现资源保护。因为我可以通过跳过登录操作,直接在浏览器发起访问图片资源的请求,如此越过登录验证这道坎。http协议的无状态性使得服务器无法知道哪个用户登录过了而哪些用户没有登录过。而每一次发起请求时要求用户输入账号密码来验证身份又是不现实的。

那么可不可以这样:登录验证通过后,服务器返回一个令牌(如一串随机数),并记录下这个令牌对应着哪个用户。对于登录之外的每个请求,都要带上这个令牌,而服务器会进行相应的验证。这样,只要这个令牌不泄漏出去,就能保证资源不会被非法访问。

也就是说,通过服务器和浏览器共同存储一些数据(浏览器端存储令牌,服务器端存储令牌即对应的账号的登录状态),如此在无状态的http协议下维持一个有状态的会话。

2.3、会话机制中的session和cookie

而浏览器端具体使用的是cookie机制,而服务器端使用的是session机制。对于使用tomcat作为web容器的java程序,当在服务器端获取session实例的时候,就会创建一个JSESSIONID,并放到cookie返回给浏览器。而浏览器端之后发起的请求中的cookie里,也会包含这个JSESSIONID。通过这个机制,就可以在通过登录验证之后,服务器端创建session并通过session.setAttribute("isLogin",true)存储用户的登录状态,之后浏览器的后续请求中,服务端会通过session.getAttribute("isLogin")获取到该请求的用户的登录状态,如果不为true,说明该请求是非法请求或者是无效请求,则不给予正常的响应信息。

2.4、对session、tomcat、web服务器的思考

这里有一块我个人觉得挺重要的知识: 对于我们在tomcat运行的web程序,通过浏览器的开发者工具,我们可以看到这个sessionId叫做JSESSIONID。而对于其他web容器,其创建的sessionId可能是别的名字。因此,当我们说php程序和java程序中sessionId不一致时,其实不是编程语言不同导致的,而是web容器的实现不同导致的。这说明session的实现是web容器完成的。tomcat的实现决定了使用tomcat作为web容器的java程序返回的sessionId的名字为JSESSIONID。
简而言之,request、response、session等是由web容器实现的。我想这些知识在学习Java Web的时候也会有提及过,但是至少于我而言,在当时是无法理解的,也不会去注意这个知识点。不知道大家的情况如何。

2.5、由web服务器、session联想到面向接口编程的好处

我们在写service层服务的时候,通常是先定义接口,然后再写具体实现。即面向接口编程。可是我一直没有感觉这样写的好处,可能因为写的代码太简单,模块架构太简单吧。

而当我意识到session是由web服务器实现的时候,才突然意识到面向接口编程有多强大,我们在获取session对象的时候,通常是这么写的:

HttpSession session = request.getSession();

也就是说,我们创建的HttpSession引用类型是接口而不是具体实现类。即session具体是由哪种web容器实现的,这对我们获取以及使用session是无感知的,除了引入的依赖不同,其余是没区别的。这样的好处是,我们可以随意的切换web容器。jetty或者tomcat。

2.6、使用redis替代session

而实际应用中,我是使用redis来替代session。为什么好好的session不用,要额外的去使用redis呢?这是因为当我重新部署war包时,该程序中所有的session都会失效。也就是说,原本处于登录验证通过的用户,他们的登录状态都会失效。而这是因为重新部署war包时,tomcat会重新加载web程序中的web.xml文件,因此会把该程序的上下文环境给清空掉,这就导致了所有的session都被清空掉。因此将信息存储在redis中。这里可以参考session机制,自己创建一个sessionId,在登录验证通过后,手动创建一个用于存储我们创建的sessionId存到cookie中,一样的,浏览器在之后的接口会回传该cookie。这样,当重新部署war程序,由于redis是独立的程序,不会受到影响。这样就能无缝的用redis实现session机制了。
并且,当该程序集群部署时,也能正常运行。(而使用session则不行)

2.7、web容器——tomcat的重要性

题外话,也是我个人觉得很重要的知识:我们写的接口即war程序之所以能被浏览器访问,很多部分功劳是因为有web服务器如tomcat。因此要好好理解web服务器——tomcat存在的意义。好好想想为什么我们写好的程序都要部署到tomcat中,而为什么我们用socket写的程序则可以不用部署到tomcat中也能被外界访问。

2.8、跨域问题

在前后端对接接口时,也经常会遇到跨域问题。如前端用vue实现而后端用java实现时,前后端联调时可能会出现:在登录页面,输入账密后点击登录,会向后端发起登录验证请求,后端验证通过后返回一些信息,但是前端却接收不到。但是单独用postman测试后端接口却是能返回数据的,而前端表示其他程序中也是用同样的方式向后端发起请求。这其实什么奇异的事情。因为出在浏览器的一个安全保护——同源策略。简单的说是因为不同源。而为什么以前学习Java Web的时候,用jsp+servlet做一个简陋web程序的时候,却不会出现跨域问题呢?简单的说是因为同源。源指的是什么?我们说跨域,跨域的主体是谁?而同源策略是什么?为什么浏览器会有同源策略?这里不去介绍,因为这一块的知识会单独写一篇的总结理解。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值