牛逼的------02单点登陆-01

cookie在浏览器是按照路径带出去的。

资料

代码

---01---

代码:

访问地址:http://localhost:8080/cookie_session_demo_Web_exploded/have-pencil.jsp

界面:

打开无痕窗口,这个是无缓存的:

COOKIE相当于身份证号,作为客户端的唯一标识。

SESSION相当于针对唯一标识,获取客户的状态。

IDEA如何导入eclipse的web项目:https://blog.csdn.net/zeal9s/article/details/90690524

servlet不存在:https://blog.csdn.net/qq_41283865/article/details/81865806

https://blog.csdn.net/wust_lh/article/details/73469789

这里直接是session了,session是自动的。

第一次访问的时候:

这个sessionId是当前的浏览器的唯一的身份认证,发送给服务器,服务器根据这个生成当前浏览器的session。seeionId只是存在浏览器的内存中。

再来:

cookie没有唯一的标识,服务器回自动给我们分配唯一标识,服务器,根据cookie取到session的。最开始是web容器给我们生成和管理的。

容器处理的是什么,就是根据cookie取出自己的session。

是web容器生成和管理的。

第一次访问的时候,生成cookie,返回给浏览器。

应用程序自己自动处理了,就是根据sessionId取出来了session。

完毕。

过程:第一次session.setAttribute返回一个cookie给浏览器。

cookie存的就是键值对

第二次根据cookie拿到session的铅笔,返回价格,自动拿cookie去找session了。

cookie是根据请求区分的,一个request一组cookie。

reponse.addCookie

request.getCookie

这些cookie在浏览器传播的,满足条件就带回来。

---

session

request.getSession(),通过cookie找到的session。

session.setAttribute

---

http://localhost:8080/cookie_session_demo_Web_exploded/have-pencil.jsp

在单点登陆我们如何设置呢?

我们访问百度就是百度的cookie:

下次我们访问新浪的话,不会把cookie发给新浪的。

什么是同一个cookie就是name secure domain path都是一样的。

删除:负数为删除

第一个域,第二个是路径,只有域和路径是一样的才会发送给服务器。

request是当前的请求。

package demo;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/path1/cookie-demo")
public class CookieDemoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
   
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// cookie增删改查
		
		// 读取cookie
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				System.out.println(cookie.getName() + ", " 
													+ cookie.getValue() + ", " 
													+ cookie.getMaxAge() + ", " 
													+ cookie.getPath() + ", "
													+ cookie.getDomain() + ", "
													+ cookie.getSecure() + ", "
													+ cookie.isHttpOnly());
			}
		}		
		// 写cookie
		Cookie cookie = new Cookie("mycookie", String.valueOf(System.currentTimeMillis())); // name & value
		cookie.setHttpOnly(false); // JavaScript不能处理
		cookie.setMaxAge(-1000); // expires:24小时过期
		cookie.setSecure(false); // 如果为true,仅支持HTTPS协议
		cookie.setPath("/path2");
		// cookie.setDomain("www.test.loc");
		
		response.addCookie(cookie);// 这句话返回给浏览器了在set-cookie消息头浏览期再次来的时候就会发送给服务器
		
		// 删除cookie
		// cookie.setMaxAge(-1); // expires:一个过去的时间
	}

}

这个第一次访问是有session的cookie的,这个是web容器自动维护的。

访问:

http://localhost:8080/cookie_session_demo_Web_exploded/path1/cookie-demo

再次访问path1:

看下重点的东西,就是域名和路径。

当设置为根路径的时候。

---

jsp如何操作cookie?

内置对象:https://www.cnblogs.com/liuyangv/p/8059848.html

设置有效期,js操作是不是https是没有意义的。

escape是转码的意思,可以把中文什么的转为不含有歧义的。

document.cookie:https://www.cnblogs.com/PopularProdigal/p/7495226.html

代码:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>cookie demo</title>
</head>
<body>
<script type="text/javascript">

	// cookie 增删改查 c1=test1; c2=new; c3=test3
	var cookies = document.cookie;
	console.log(cookies);
	
	document.cookie="c3=test3";
	document.cookie="c2=new";
	// httpOnly 不允许js操作
	docment.cookie="c4=test4;expires=" + [GMT时间] + ";path=/;domain=www.test.com;secure"
	
	var d = new Date().getTime();
	d += 24 * 60 * 60 * 1000;
	
	document.cookie = "c1=test1;expires=" + new Date(d).toGMTString() ;
	document.cookie = "c2=" + escape("内容转码防错误") + "";
	
	// 去空格
	function trim(str) { 
		return str.replace(/(^\s*)|(\s*$)/g, "");
   }
	
	// 获取cookie值    c1=test1; c2=%12%34%56%78%33%aba%20bc escape unescape
	function getCookie(name) {
		var cookies = document.cookie.split(";");
		for (var i = 0, len = cookies.length; i < len; ++i) {
			var cookie = cookies[i].split("=");
			if (name === trim(cookie[0])) {
				return unescape(trim(cookie[1]));// 对特殊字符转码
			}
		}
	}
	
	console.log(getCookie("c1"));
	console.log(getCookie("c2"));
	
	// 新增cookie(如果存在同名cookie,起到修改作用)
	// expiresDay为有效天数
	// domain提升到顶级域时,可使用.test.com形式
	// 用js设置cookie,httpOnly属性浏览器支持情况不同,用js设置一般来说也没有意义
	// c1=中文2;expires=3-6 2014GMT;path=/;domain=.test.com;secure
	function addCookie(name, value, expiresDay, path, domain, isSecure) {
		var tmp = name + "=" + escape(value);
		
		if (expiresDay) {
			var d = new Date().getTime();
			d += expiresDay * 24 * 60 * 60 * 1000;
			tmp += ";expires=" + new Date(d).toGMTString();
		} 
		
		if (path) {
			tmp += ";path=" + path;
		}
		
		if (domain) {
			tmp += ";domain=" + domain;
		}
		
		if (isSecure) {
			tmp += ";secure";
		}
		
		console.log(tmp);
		document.cookie = tmp;
	}
	
	
	// 删除cookie,没有真正的删除,只能将cookie过期时间设置为过去时间,当浏览器关闭或重载页面时cookie被清除
	function delCookie(name) {
		document.cookie = name + "=anyval;expires=" + new Date(0).toGMTString();
	}
	
	delCookie("c1");
	console.log(getCookie("c1"));

	delCookie("new1");
	delCookie("new2");
	
	addCookie("new1", "新的一个");
	addCookie("new2", "2new", null, "/path1", null, true);
	
</script>
</body>
</html>

---

问题:

---

cookie放在fliter里面。

拦截器:

session设置过其时间:https://blog.csdn.net/t2080305/article/details/81063737

---02---

认证中心:验证token生成token 登陆页面 注销接口。

客户端:拦截请求提取令牌交给认证中心,成功附加到请求,失败到认证中心的登陆页面。

转发和重定向:https://blog.csdn.net/weixin_40001125/article/details/88663468

灰白色是客户端,蓝色是认证中心,绿色是业务系统。

解读:

没有跨域的单点登陆:

单点登陆的服务端:

1.退出登陆,删除token与用户的关联 和 cookie。

2.没有登陆:get登陆请求过来,转发到单点登陆的服务器进行登陆(此时携带用户的地址,提交登陆信息将令牌和user关联加到内存,将令牌存到cookie),重定向到携带的用户地址再次走客户端的过滤器。

3.登陆了:带token发送http请求,验证token的有效性,通过cookie里面的令牌验证是否有对应的user,返回user没有返回null。

单点登陆的客户端(过滤器集成到用户),每次请求都要通过http请求去服务端验证:

1.从cookie中获取令牌,和当前路径。

2.http去服务端验证令牌不存在或者验证令牌是无效的,携带当前路径到服务端的登陆请求,转发到登陆页面。

3.验证通过,把用户加到request中,进入下次用户的下一个拦截器。

单点登陆的用户

1.集成客户端过滤器给自己

map的key就是token value就是user

cookie的name就是token value就是token

代码:

数据库的表:

 

---03---

重新访问:https://blog.csdn.net/qq_40910746/article/details/109618404

看下客户端首先访问:

同理app2

服务端模块的实现。

最后乱码是登陆成功跳转的界面。

首先看服务端的登陆授权功能:

我这个项目终于启动起来了:

http://localhost:8080/app2/

第一步:

两个方法,一个是get一个是post

get就是到登录页面

post就是表单提交处理

package demo.sso.auth.controller;

import java.io.IOException;
import java.net.URLDecoder;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import demo.sso.TokenUserData;
import demo.sso.auth.service.UserAccountService;
import demo.sso.common.KeyGenerator;
import demo.sso.common.StringUtil;
import demo.sso.model.User;

/**
 * user login
 */
@WebServlet("/login")
public class UserLoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;

	//private static String DOMAIN = ".test.loc";

	private UserAccountService userAccountService = new UserAccountService();

	/**
	 * 进入登录页
	 */
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		// 获得原始请求的url并保存传递,当登录成功时,让浏览器再次跳转到这个url
		String origUrl = req.getParameter("origUrl");
		req.setAttribute("origUrl", origUrl);

		req.getRequestDispatcher("/WEB-INF/view/login.jsp").forward(req, resp);
	}

	/**
	 * 登录表单提交时处理
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		String account = request.getParameter("account");
		String passwd = request.getParameter("passwd");

		String origUrl = request.getParameter("origUrl");

		// 按account查找用户
		User user = null;
		try {
			user = userAccountService.findUserByAccount(account);

			if (user != null) {
				if (user.getPasswd().equals(passwd)) { // 判断密码是否正确
					// 1 生成token
					String token = KeyGenerator.generate();
					// 2 将token user存储到全局唯一数据结构中
					TokenUserData.addToken(token, user);
					// 3 写cookie JVM 
					Cookie tokenCookie = new Cookie("token", token);
					tokenCookie.setPath("/");
					//tokenCookie.setDomain(DOMAIN);
					tokenCookie.setHttpOnly(true);
					response.addCookie(tokenCookie);

					// 4 跳转到原请求
					if (StringUtil.isEmpty(origUrl)) {
						origUrl = "login_success";
					} else {
                       // 跳转到请求的地址
						origUrl = URLDecoder.decode(origUrl, "utf-8");
					}
					response.sendRedirect(origUrl);
				} else {
					backToLoginPage(request, response, account, origUrl,
							"密码不正确");
				}
			} else { // 用户不存在
				backToLoginPage(request, response, account, origUrl, "用户不存在");
			}

		} catch (SQLException e) {
			e.printStackTrace();
			backToLoginPage(request, response, account, origUrl, "发生系统错误!");
		}

	}

	private void backToLoginPage(HttpServletRequest req,
			HttpServletResponse resp, String account, String origUrl,
			String errInfo) throws ServletException, IOException {

		req.setAttribute("account", account);
		req.setAttribute("origUrl", origUrl);
		req.setAttribute("errInfo", errInfo);

		req.getRequestDispatcher("/WEB-INF/view/login.jsp").forward(req, resp);
	}
}

首先是get,则直接把跳转的地址存入reponse,转发到登录页面。

附加

存的全局的键值对的建是token 值是当前的user。把token放在cookie里面。

提交请求之后则:

protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		String account = request.getParameter("account");
		String passwd = request.getParameter("passwd");

		String origUrl = request.getParameter("origUrl");

		// 按account查找用户
		User user = null;
		try {
			user = userAccountService.findUserByAccount(account);

			if (user != null) {
				if (user.getPasswd().equals(passwd)) { // 判断密码是否正确
					// 1 生成token
					String token = KeyGenerator.generate();
					// 2 将token user存储到全局唯一数据结构中
					TokenUserData.addToken(token, user);
					// 3 写cookie JVM 
					Cookie tokenCookie = new Cookie("token", token);
					tokenCookie.setPath("/");
					//tokenCookie.setDomain(DOMAIN);
					tokenCookie.setHttpOnly(true);
					response.addCookie(tokenCookie);

					// 4 跳转到原请求
					if (StringUtil.isEmpty(origUrl)) {
						origUrl = "login_success";
					} else {
						origUrl = URLDecoder.decode(origUrl, "utf-8");
					}
					response.sendRedirect(origUrl);
				} else {
					backToLoginPage(request, response, account, origUrl,
							"密码不正确");
				}
			} else { // 用户不存在
				backToLoginPage(request, response, account, origUrl, "用户不存在");
			}

		} catch (SQLException e) {
			e.printStackTrace();
			backToLoginPage(request, response, account, origUrl, "发生系统错误!");
		}

	}

---

系统之间的通信方式:

关于web-inf路径:https://www.cnblogs.com/lbrs/p/12122325.html

注销:

什么是同一个cookie,一定要路径,domin都相同才可以的。

---04---

客户端模块的实现,客户端是整合到app里面的。:

代码:

package demo.sso.client;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import demo.sso.client.util.CookieUtil;

/**
 * SSO客户端模块Filter
 * 
 * @author Administrator
 *
 */
public class SSOFilter implements Filter {

	// SSO Server登录页面URL
	private static final String SSO_LOGIN_URL = "/server/login",
			SSO_VALIDATE_URL = "http://localhost:8080/server/validate";

	// 拦截操作
	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {

		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;

		// 从请求中提取token
		String token = CookieUtil.getCookie(req, "token");

		// 本次请求的完整路径 不包括?的
		String origUrl = req.getRequestURL().toString();
		String queryStr = req.getQueryString();
		if (queryStr != null) {
			origUrl += "?" + queryStr;
		}

		// token 不存在,跳转到SSOServer用户登录页 重定向
		if (token == null) {
			resp.sendRedirect(SSO_LOGIN_URL + "?origUrl="
					+ URLEncoder.encode(origUrl, "utf-8"));
		} else { // token存在,验证有效性
			URL validateUrl = new URL(SSO_VALIDATE_URL + "?token=" + token);
			HttpURLConnection conn = (HttpURLConnection) validateUrl
					.openConnection();

			conn.connect();
			InputStream is = conn.getInputStream();

			byte[] buffer = new byte[is.available()];
			is.read(buffer);

			String ret = new String(buffer);

			if (ret.length() == 0) { // 返回空字符串,表示 token无效
				resp.sendRedirect(SSO_LOGIN_URL + "?origUrl="
						+ URLEncoder.encode(origUrl, "utf-8"));
			} else {
				String[] tmp = ret.split(";");
				User user = new User();
				for (int i = 0; i < tmp.length; ++i) {
					String[] attrs = tmp[i].split("=");
					switch (attrs[0]) {
					case "id":
						user.setId(Integer.parseInt(attrs[1]));
						break;
					case "name":
						user.setName(attrs[1]);
						break;
					case "account":
						user.setAccount(attrs[1]);
						break;
					}
				}
				request.setAttribute("user", user);
				chain.doFilter(request, response);
			}
		}
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		// do nothing
	}

	@Override
	public void destroy() {
		// do nothing
	}
}

解读:request.getUrl得到的是什么呢:不包括问号和以后的部分的。

通过了 把user存在request里面

mvc配置过滤器:https://www.cnblogs.com/LiuOOP/p/11208830.html

生效其它的:https://blog.csdn.net/lero524/article/details/107832749

非maven项目打包jar:https://www.cnblogs.com/lianxuan1768/p/12752482.html

打包jar包:https://blog.csdn.net/qq_22136439/article/details/90692509

如何整合客户端呢?

是在app的filter配置的。

看下app2:

代码:

package app2;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import demo.sso.client.User;

public class PrivilegeFilter implements Filter {

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

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		// 集成SSO前
		// User loginUser = ((HttpServletRequest)request).getSession().getAttribute("loginUser");
		
		// 从上一个Filter(SSOFilter)存入的属性中获取user,能执行到此处,一定是已登录
		User user = (User) request.getAttribute("user");
		// 可以根据user信息获得与本系统相关的用户业务信息
		// Empl empl = EmplService.findEmplByUser(user.getId());
		
		// 示范一个更详细的需要判定
		String acc = user.getAccount();
		
		if ("zs".equals(acc)) {
			response.getWriter().write("zhangsan is forbidden!");
		} else {
			chain.doFilter(request, response);
		}
	}

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

	}

}

---05---

浏览器的跨域安全限制:

jsonp举例:

当前在localhost域和127.0.0.1不是一个域。

 

---06---

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园悬赏任务平台对字典管理、论坛管理、任务资讯任务资讯公告管理、接取用户管理、任务管理、任务咨询管理、任务收藏管理、任务评价管理、任务订单管理、发布用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行校园悬赏任务平台程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。校园悬赏任务平台的开发让用户查看任务信息变得容易,让管理员高效管理任务信息。 校园悬赏任务平台具有管理员角色,用户角色,这几个操作权限。 校园悬赏任务平台针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理任务信息,管理任务资讯公告信息等内容。 校园悬赏任务平台针对用户设置的功能有:查看并修改个人信息,查看任务信息,查看任务资讯公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看任务,删除任务操作,新增任务操作,修改任务操作。任务资讯公告信息管理页面提供的功能操作有:新增任务资讯公告,修改任务资讯公告,删除任务资讯公告操作。任务资讯公告类型管理页面显示所有任务资讯公告类型,在此页面既可以让管理员添加新的任务资讯公告信息类型,也能对已有的任务资讯公告类型信息执行编辑更新,失效的任务资讯公告类型信息也能让管理员快速删除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值