sso单点登录

Posted popcorn丫

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sso单点登录相关的知识,希望对你有一定的参考价值。

同域下的单点登录:

现在假设有两个系统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拿到用户,如果成功拿到,则登录成功,如果拿不到则返回登陆页面。

以上是关于sso单点登录的主要内容,如果未能解决你的问题,请参考以下文章

SSO单点登录

手把手教你用代码实现SSO单点登录

简单代码实现JWT(json web token)完成SSO单点登录

php 怎么实现单点登录?

《果然新鲜》电商项目(37)-SSO单点登录(改造SSO认证服务登录界面)

sso单点登录实现