单点登录详解(一)--使用Cookie+Filter实现单点登录

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013213157/article/details/77427235
    单点登陆分两种,一种是系统之间一级域名相同,如www.bbs.itcast.cn及www.news.itcast.cn这两个域名,一级域名(itcast.cn)相同,这两个系统可以拿到对方的cookie,通过cookie+Filter就能实现单点登录,另一种,如www.bbs.com及www.news.com,这两个网站没有任何关系,不在同一个域中。这种情况下节再讲。

   首先eclipse创建一个web工程,这里写一个简单的登陆页面,这里直接修改index.jsp作为登录页:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
  </head>
 
  <body>
  <c:choose>
   <c:when test="${not empty sessionScope.user}">
     欢迎你:${sessionScope.user}
    </c:when>
    <c:otherwise>
     你还没有登录,请先登录:
     <form action="<%=path %>/login" method="post">
      userName:<input type="text" name="userName"><br>
      password:<input type="password" name="password"><br>
      <input type="submit" value="登录">
     </form>
    </c:otherwise>
  </c:choose>
  
   
  </body>
</html>

然后写一个servlet接收该请求:

public class LoginServlet extends HttpServlet {

 /**
  * Constructor of the object.
  */
 public LoginServlet() {
  super();
 }

 /**
  * Destruction of the servlet. <br>
  */
 public void destroy() {
  super.destroy(); // Just puts "destroy" string in log
  // Put your code here
 }

 /**
  * The doGet method of the servlet. <br>
  *
  * This method is called when a form has its tag value method equals to get.
  *
  * @param request the request send by the client to the server
  * @param response the response send by the server to the client
  * @throws ServletException if an error occurred
  * @throws IOException if an error occurred
  */
 public void doGet(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {

  this.doPost(request, response);
 }

 /**
  * The doPost method of the servlet. <br>
  *
  * This method is called when a form has its tag value method equals to post.
  *
  * @param request the request send by the client to the server
  * @param response the response send by the server to the client
  * @throws ServletException if an error occurred
  * @throws IOException if an error occurred
  */
 public void doPost(HttpServletRequest request, HttpServletResponse response)
   throws ServletException, IOException {

  String userName = request.getParameter("userName");
  String password = request.getParameter("password");
  
  if(userName != null && password != null){
   if(userName.equals(password)){//登录成功,实际应查询数据库
    request.getSession().setAttribute("user", userName);
    
    //向客户端写入cookie
    Cookie c = new Cookie("sso",userName);
    
    c.setMaxAge(3600);//1小时
    c.setDomain(".itcast.cn");//www.bbs.itcast.cn www.news.itcast.cn
    c.setPath("/");
    
    response.addCookie(c);
   }
  }
  
  response.sendRedirect(request.getContextPath() + "/index.jsp");
 }

 /**
  * Initialization of the servlet. <br>
  *
  * @throws ServletException if an error occurs
  */
 public void init() throws ServletException {
  // Put your code here
 }

}

说明:c.setDomain(".itcast.cn");设置cookie的域,这样的话所有一级域名为itcast.cn的系统都能拿到这个cookie.
c.setPath("/");表示部署在同一服务器下的应用都能拿到这个cookie,如果写成c.setPath("/sso_bbs");那只有这个sso_bbs的应用能拿到这个cookie.
这时候我们默认访问localhost:8080/index.jsp,虽然能正确访问页面,但是发现浏览器并没有记录名字为“sso"的cookie,这是为什么,因为我们设置了这个cookie的domain一级域名只能是itcast.cn,而我们访问的并不是这样一个地址,所以没有产生cookie,所以需要访问类似www.bbs.itcast.cn这样的网址才行,但是现在这样访问肯定不行。
所以我们还需要修改一些配置,首先修改系统hosts文件:
增加最下面这一行,这时候去访问www.bbs.itcast.cn,发现还是找不到应用服务器的项目资源,而输入localhost为什么就可以访问(这里设置工程访问端口为80,免去输入指定的端口)。这是因为在访问localhost时候tomact服务器会默认去webapps中访问项目资源,所以我们需要去修改tomact中的配置文件,打开tomact安装目录下的conf的server.xml文件找到Host节点,有如下配置,这就是为什么在访问localhost的时候,能访问到项目资源的原因:

   修改配置文件:

当然为了不影响tomact原始逻辑,可以选择不修改原有节点,而是增加一个Host节点:
修改完配置文件,然后在tomact的与webapps平级的目录下创建bbs目录,将项目拷贝到bbs目录,将项目目录重命名为bbs,这时候访问www.bbs.itcast.cn/bbs就可以了,但是为了方便,不想加bbs这样的项目目录后缀,那么要怎样改呢?
大家会发现,当我们访问启动tomact的时候,直接访问localhost,可以进到tomact的首页,为什么这里不需要加项目后缀,这是因为这个资源在webapps下的ROOT目录下,tomact默认,当不写项目后缀的情况下,tomact默认加载ROOT目录下的资源,所以,很简单,我们只需要将刚才重命名为bbs的目录命名为ROOT,这时候直接访问www.bbs.itcast.cn就可以访问到项目了。

现在我们先实现一个单点登录无关的功能,就是“记住我”。这样的功能,也就是当一个用户第一次登陆了,关闭浏览器,过一段时间去访问网站,无需再次登录。
这个实现的思路大致是,写一个过滤器,遍历cookie,当存在我们登陆时写入的cookie,就设置session属性。过滤器代码如下:
public class AutoLoginFilter implements Filter {

 public void destroy() {
  // TODO Auto-generated method stub

 }

 public void doFilter(ServletRequest req, ServletResponse resp,
   FilterChain chain) throws IOException, ServletException {

  HttpServletRequest request = (HttpServletRequest) req;
  
  if(request.getSession().getAttribute("user")== null){
   Cookie[] cs = request.getCookies();

   if (cs != null && cs.length > 0) {
    for (Cookie c : cs) {
     String cName = c.getName();
     if (cName.equals("sso")) {
      String userName = c.getValue();
      request.getSession().setAttribute("user", userName);
     }
    }
   }
  }

  chain.doFilter(request, resp);

 }

 public void init(FilterConfig arg0) throws ServletException {
  // TODO Auto-generated method stub

 }

}
然后在web,xml配置过滤器:
<filter>
  <filter-name>autoLogin</filter-name>
  <filter-class>cn.itcast.sso.filter.AutoLoginFilter</filter-class>
 </filter> 
 <filter-mapping>
  <filter-name>autoLogin</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
这样就实现了“记住我”这种功能。然后为了验证单点登录,可以再新建一个工程,代码可以跟之前工程类似,只需改一下登陆成功返回的页面显示,以区分之前的项目。在hosts中新增映射:
然后修改在tomact配置文件中再新增一个Host节点:
然后将新建的工程放入news目录中,修改项目名称为ROOT,再访问www.news.itcast.cn,发现无需登录。



展开阅读全文

没有更多推荐了,返回首页