同域下的单点登录:
现在假设有两个系统demo1,和demo2它们分别有自己的登陆方法如下:
@PostMapping("/doLogin") public String doLogin(String username,String password,String url,HttpServletResponse response){ boolean result = SSOUtil.loginCheck(username,password); if(result){ Cookie cookie = new Cookie("ssoCookie","sso");//这里的cookie需要一定的规则 cookie.setDomain(".bxw.com");//将cookie设置为同父域 cookie.setPath("/");//设置cookie的路径为根路径,也就是同域cookie都有效 response.addCookie(cookie); return "/success"; } return ""; }
在父域中设置cookie:cookie.setDomain(".bxw.com");//将cookie设置为同父域
在SSOUtil类中的loginCheck方法中检验用户名密码的正误,如果检验通过则result的结果为true,这样在本域中会产生键为ssoCookie,值为sso的cookie(在sso中,不同用户的键一般是相同的,而值则根据一定规则生成独属于自己的值,这里为了简便统一写为sso)。
现在假设demo1系统已经登录,刷新demo2的登陆页面。
@GetMapping("/") public String toLogin(HttpServletRequest request){
Cookie[] cookies = request.getCookies(); if(SSOUtil.cookieCheck(cookies)){ return "/success"; }else{ return "/login"; } }
demo2在跳转登录页面的方法中会首先检验是否有键为ssoCookie,值为sso的cookie,如果有的话,则返回登录成功的界面否则返回登陆页面。检验cookie方法如下。
public static boolean cookieCheck(Cookie[] cookies){ if(cookies!=null){ for(Cookie cookie:cookies){ if("ssoCookie".equals(cookie.getName()) && "sso".equals(cookie.getValue())){ return true; } } } return false; }
同父域下的单点登录:
与同域下的单点登录类似,只不过在产生cookie时,需要设置cookie的域为父域,具体方法如下:
@PostMapping("/doLogin") public String doLogin(String username,String password,String url,HttpServletResponse response){ boolean result = SSOUtil.loginCheck(username,password); if(result){ Cookie cookie = new Cookie("ssoCookie","sso");//这里的cookie需要一定的规则 cookie.setDomain(".bxw.com");//将cookie设置为同父域 cookie.setPath("/");//设置cookie的路径为根路径,也就是同域cookie都有效 response.addCookie(cookie); return "/success"; } return ""; }
需要修改cookie的验证方法,这里我们假设有一个项目demo3专门用来检验cookie。因为子域可以拿到父域的cookie,demo2遍历域中的cookie,拿到键为ssoCookie的cookie发送到demo3进行检验,这里采用http请求。
@GetMapping("/") public String toLogin(HttpServletRequest request){ Cookie[] cookies = request.getCookies(); String result = "false"; if(cookies!=null){ for(Cookie cookie:cookies){ if("ssoCookie".equals(cookie.getName())){ Map<String,String> map = new HashMap<String,String>(); map.put("name",cookie.getName()); map.put("value",cookie.getValue()); result = SSOUtil.sendGet("http://client.bxw.com:7777/springboot/sso/checkCookie",map); } } } if("true".equals(result)){ return "/success"; }else{ return "/login"; } }
检验cookie其实应该写一个过滤器,这里为了方便直接写在跳转登录页面的方法中,一般在参数过多的情况下会采用map传参。
http请求如下,这里用了get请求。
public static String sendGet(String url, Map<String,String> cookieMap) { String result = ""; BufferedReader in = null; try { StringBuffer urlNameString = new StringBuffer(url + "?"); for(Map.Entry<String,String> tmp:cookieMap.entrySet()){ urlNameString.append(tmp.getKey()+"="+tmp.getValue()+"&"); } String urlVal = urlNameString.substring(0,urlNameString.length()-1).toString(); URL realUrl = new URL(urlVal); // 打开和URL之间的连接 URLConnection connection = realUrl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/5.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立实际的连接 connection.connect(); // 获取所有响应头字段 Map<String, List<String>> map = connection.getHeaderFields(); // 遍历所有的响应头字段 for (String key : map.keySet()) { System.out.println(key + "--->" + map.get(key)); } // 定义 BufferedReader输入流来读取URL的响应 in = new BufferedReader(new InputStreamReader( connection.getInputStream())); String line; while ((line = in.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送GET请求出现异常!" + e); } // 使用finally块来关闭输入流 finally { try { if (in != null) { in.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return result; }
demo3中对demo2发出的http请求处理。
@GetMapping("/checkCookie") public String cookieCheck(HttpServletRequest request){ String CookieName = request.getParameter("name"); String CookieValue = request.getParameter("value"); Boolean flag = false;//验证是否成功 if(CookieName.equals("ssoCookie") && CookieValue.equals("sso")){ flag = true; } return flag.toString(); } /* public void cookieCheck(HttpServletRequest request, HttpServletResponse response){ String CookieName = request.getParameter("name"); String CookieValue = request.getParameter("value"); Boolean flag = false;//验证是否成功 if(CookieName.equals("ssoCookie") && CookieValue.equals("sso")){ flag = true; } try{ response.getWriter().print(flag); }catch (IOException e){ e.printStackTrace(); } }*/
跨域单点登录:
如果是跨域的话,在demo2登陆时需要去请求demo1域中的单点登录的cookie拿到用户,如果成功拿到,则登录成功,如果拿不到则返回登陆页面。