基于cookie共享实现单点登录

server/2025/1/12 3:34:49/

架构图

sso认证中心

  基于传统的servlet 方案

   提供核心接口 

       1.登录接口

       2.认证接口 判断是否已经登录  也可以进行手动的用户信息同步到各个子服务

        3.登录页面

       

/**基于传统的 servlet 方案
*/
@WebServlet(urlPatterns = "/login.do")
public class LoginController extends HttpServlet {private static final String LOGIN_SESSION ="LOGIN_SESSION";private static final String LOGIN_TOKEN ="LOGIN_TOKEN";@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {HttpSession session = req.getSession();String username = req.getParameter("username");String password = req.getParameter("password");
// 重定向的地址String url = req.getParameter("callback");if ("admin".equals(username) && "admin".equals(password)){
//            登录成功  存储用户信息到session中SessionMng mng = new SessionMng(username,password);session.setAttribute(LOGIN_SESSION,mng);//登录成功后 返回重定向的地址 if (url !=null && !url.equals("")){resp.sendRedirect(url);}else{req.getRequestDispatcher("/index.jsp").forward(req,resp);}}else{
//     登录失败 重定向到登录地址req.getRequestDispatcher("/login.jsp").forward(req,resp);}}
}

web.xml  配置 cookie 的名称   domain   path  必须是父域名 让子域名共享 

<?xml version="1.0" encoding="UTF-8"?>
<web-appversion="4.0"xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:javaee="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xml="http://www.w3.org/XML/1998/namespace"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"><display-name>Archetype Created Web Application</display-name><session-config><cookie-config><name>session</name><domain>at.com</domain><path>/</path></cookie-config></session-config>
</web-app>
package com.me.web.controller;import com.alibaba.fastjson.JSONObject;
import com.me.domain.RedisCache;
import com.me.domain.SessionMng;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;/***  验证登录请求是否合法*/
@WebServlet("/validlogin")
public class ValidLoginController extends HttpServlet {private static final String LOGIN_SESSION ="LOGIN_SESSION";private static final String LOGIN_TOKEN ="LOGIN_TOKEN";@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req,resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/***  从请求中获取 cookie 判断 是否携带了 请求的cookie session*/Cookie[] cookies = req.getCookies();if (cookies!=null){for (int i = 0; i < cookies.length; i++) {System.out.println(cookies[i].getName()+":"+cookies[i].getValue());}}JSONObject obj = new JSONObject();
//        从本地的session中获取 用户信息 获取不到则视为未登录HttpSession session = req.getSession();SessionMng  pbj = (SessionMng) session.getAttribute(LOGIN_SESSION);if (pbj!=null ){obj.put("success",true);}else{obj.put("success",false);}resp.getWriter().write(obj.toJSONString());}
}

登录页 login.jsp


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
String callback = request.getParameter("callback");
if (callback == null){callback ="";
}
%>
<html>
<head><title>login</title>
</head>
<body>
<form method="post" action="${pageContext.request.contextPath}/login.do"><input name="callback" type="hidden" value="<%=callback%>" />username: <input name="username" value=""> <br>password:<input name="password" value=""> <br><input type="submit" value="login"></form>
</body>
</html>

serviceA 

基于过滤器实现请求拦截和判断

package com.me.web.filter;import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;import javax.servlet.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import java.io.IOException;
import java.net.HttpCookie;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;public class SSOFilter implements Filter {private String VALID_LOGIN_URL ="";private String REDIRECT_LOGIN_URL ="";@Overridepublic void init(FilterConfig filterConfig) throws ServletException {VALID_LOGIN_URL = filterConfig.getInitParameter("VALID_LOGIN_URL");REDIRECT_LOGIN_URL = filterConfig.getInitParameter("REDIRECT_LOGIN_URL");}@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse resp = (HttpServletResponse) response;/*从本地的cookie中获取认证中心的session  如果获取不到 则直接 退出登录 重定向到认证中心的登录地址*/Cookie[] cookies = req.getCookies();if (cookies==null || cookies.length==0){resp.sendRedirect(REDIRECT_LOGIN_URL+"?callback="+req.getRequestURL());return;}Optional<Cookie> op = Arrays.stream(cookies).filter(c -> c.getName().equals("session")).findFirst();if (op.isPresent()){/**  获取到cookie后 去认证中心校验是否登录 返回 true false 成功则通过*  否则 重定向到登录地址* */Cookie cookie = op.get();String token = cookie.getValue();boolean b = validLogin(token,req);if (b){chain.doFilter(request,response);}else{resp.sendRedirect(REDIRECT_LOGIN_URL+"?callback="+req.getRequestURL());}}else{resp.sendRedirect(REDIRECT_LOGIN_URL+"?callback="+req.getRequestURL());
//            chain.doFilter(request,response);}}@Overridepublic void destroy() {}/***  调用远程接口 校验是否登录  同步用户信息到本地* @param token* @param req* @return*/public boolean validLogin(String token,HttpServletRequest req){HttpSession session = req.getSession();String url= VALID_LOGIN_URL;Collection<HttpCookie> collect = new ArrayList();/*调用接口时 把cookie 带上 否则无法实现session获取用户信息和判断* */Arrays.stream(req.getCookies()).forEach(p->{HttpCookie c  = new HttpCookie(p.getName(), p.getValue());collect.add(c);});String body= HttpRequest.get(url).cookie(collect).execute().body() ;JSONObject obj = JSON.parseObject(body);if (obj !=null){Boolean success = obj.getBoolean("success");if (success){return success;}else{return false;}}return false;}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-appversion="4.0"xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:javaee="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xml="http://www.w3.org/XML/1998/namespace"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"><display-name>Archetype Created Web Application</display-name><filter><filter-name>SSOFilter</filter-name><filter-class>com.me.web.filter.SSOFilter</filter-class><init-param><param-name>VALID_LOGIN_URL</param-name><param-value>http://at.com:9081/sso-server/validlogin</param-value></init-param><init-param><param-name>REDIRECT_LOGIN_URL</param-name><param-value>http://at.com:9081/sso-server/login.jsp</param-value></init-param></filter><filter-mapping><filter-name>SSOFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><session-config><cookie-config><domain>service.at.com</domain><path>/</path></cookie-config></session-config>
</web-app>

验证

认证中心登录地址:http://at.com:9081/sso-server/login.jsp   

serviceA: http://service.at.com:8081/serviceA/index.jsp

在浏览器输入http://service.at.com:8081/serviceA/index.jsp

初次未登录会被重定向到http://at.com:9081/sso-server/login.jsp?callback=http://service.at.com:8081/serviceA/index.jsp

登录成功后 会被重定向到    http://service.at.com:8081/serviceA/index.jsp 

验证结束


http://www.ppmy.cn/server/157658.html

相关文章

CSS第二天导读

目录 Emmet语法 CSS的复合选择器 CSS的元素显示模式 CSS的背景 CSS的三大特性 CSS的注释 1.Emmet语法 1.1 快速生成HTML结构语法 生成标签直接输入标签名 按tab键即可&#xff0c;比如div然后tab&#xff0c;即可生成div如果想要生成多个标签&#xff0c;加上*就可以了&…

飞书机器人告警实现

功能实现说明 1. 准备好config.json文件&#xff0c;用于存放配置文件信息 2. 准备好config.py用于读取配置文件信息 3. feishu.py用于实现获取临时token以及推送消息至指定机器人并推到指定飞书用户 config.json {"auth":{"app_id": "cli_xxxxx…

HTML实战课堂之简单的拜年程序

一、目录&#xff1a; &#xfffc;&#xfffc; 一、目录&#xff1a; 二、祝福 三&#xff1a;代码讲解 &#xff08;1&#xff09;详细解释&#xff1a; 1.HTML部分 2. CSS部分 三、运行效果&#xff08;随机截图&#xff09;&#xff1a; 四、完整代码&#xff1a; 二、祝福…

基于 Boost.Asio 和 Boost.Beast 的异步 HTTP 服务器(学习记录)

已完成功能&#xff1a; 支持 GET 和 POST 请求的路由与回调处理。 解析URL请求。 单例模式 管理核心业务逻辑。 异步 I/O 技术和 定时器 控制超时。 通过回调函数注册机制&#xff0c;可以灵活地为不同的 URL 路由注册处理函数。 1. 项目背景 1.1 项目简介 本项目是一个基于…

2025年第三届“华数杯”国际赛A题解题思路与代码(Matlab版)

游泳竞技策略优化模型代码详解&#xff08;MATLAB版&#xff09; 第一题&#xff1a;速度优化模型 本部分使用MATLAB实现游泳运动员在不同距离比赛中的速度分配策略优化。 1. 模型概述 模型包含三个主要文件&#xff1a; speed_optimization.m: 核心优化类plot_speeds.m: …

apache age:22023,42883,等报错信息

apache age 各种类型不匹配 函数找不到 以下是对Apache AGE、PostgreSQL以及Cypher语法的详细介绍: 一、Apache AGE 定义:Apache AGE(A Graph Extension)是一个基于PostgreSQL的图数据库扩展插件。它结合了PostgreSQL的先进SQL查询功能和事务支持,以及图数据库的灵活性和…

551 灌溉

常规解法&#xff1a; #include<bits/stdc.h> using namespace std; int n,m,k,t; const int N105; bool a[N][N],b[N][N]; int cnt; //设置滚动数组来存贮当前和下一状态的条件 //处理传播扩散问题非常有效int main() {cin>>n>>m>>t;for(int i1;i&l…

SQL Server中可以通过扩展事件来自动抓取阻塞

在SQL Server中可以通过扩展事件来自动抓取阻塞&#xff0c;以下是详细流程&#xff1a; 开启阻塞跟踪配置&#xff1a; • 执行以下SQL语句来启用相关配置&#xff1a; EXEC sp_configureshow advanced options, 1; RECONFIGURE; EXEC sp_configure blocked process thresh…