精华内容
下载资源
问答
  • 单点登录跨域iframe互相通信方案 ,内含详细步骤,可以实现不同源的域名互相通信。亲测,可用哦。也可以到我的博客查看具体操作步骤。
  • 主要介绍了vue+springboot前后端分离实现单点登录跨域问题的解决方法,需要的朋友可以参考下
  • 原文来自 © 呆萌钟 vue+springboot前后端分离实现单点登录跨域问题处理 最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的。因为后台系统没有登录功能,但是公司要求统一登录登录...

    转载声明:商业转载请联系作者获得授权,非商业转载请注明出处.原文来自 © 呆萌钟 vue+springboot前后端分离实现单点登录跨域问题处理

    最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的。因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统。那就意味着做单点登录咯,至于不知道什么是单点登录的同学,建议去找一下万能的度娘。

    刚接到这个需求的时候,老夫心里便不屑的认为:区区登录何足挂齿,但是,开发的过程狠狠的打了我一巴掌(火辣辣的一巴掌)。。。,所以这次必须得好好记录一下这次教训,以免以后再踩这样的坑。

    我面临的第一个问题是跨域,浏览器控制台直接报CORS,以我多年开发经验,我果断在后台配置了跨域配置,代码如下:

    @Configuration
    public class CorsConfiguration {
    
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**")
                            .allowedHeaders("*")
                            .allowedMethods("*")
                            .allowedOrigins("*");
                }
            };
        }
    }

    这个配置就是允许所有mapping,所有请求头,所有请求方法,所有源。改好配置之后我果断重启项目,看效果,结果发现根本没法重定向跳转到单点登录页面,看浏览器报错是跨域导致的,我先上我登录拦截器的代码

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //用户已经登录
        if (request.getSession().getAttribute("user") != null) {
            return true;
        }
        //从单点登录返回之后的状态,本系统还不处于登录状态
        //根据code值去获取access_token,然后再根据access_token去获取用户信息,并将用户信息存到session中
        String state = request.getParameter("state");
        String uri = getUri(request);
        if (isLoginFromSSO(state)) {
            String code = request.getParameter("code");
            Object cacheUrl = request.getSession().getAttribute(state);
            if (cacheUrl == null) {
                response.sendRedirect(uri);
                return false;
            }
            HttpUtil client = new HttpUtil();
            StringBuffer sb = new StringBuffer();
            sb.append("code=").append(code)
                    .append("&grant_type=").append("authorization_code")
                    .append("&client_id=").append(SSOAuth.ClientID)
                    .append("&client_secret=").append(SSOAuth.ClientSecret)
                    .append("&redirect_uri=").append(URLEncoder.encode((String) cacheUrl));
            String resp = client.post(SSOAuth.AccessTokenUrl, sb.toString());
            Map<String, String> map = new Gson().fromJson(resp, Map.class);
            //根据access_token去获取用户信息
            String accessToken = map.get("access_token");
            HttpUtil http = new HttpUtil();
            http.addHeader("Authorization", "Bearer " + accessToken);
            String encrypt = http.get(SSOAuth.UserUrl);
            String userinfo = decryptUserInfo(encrypt);
            //封装成user对象
            User user = new Gson().fromJson(userinfo, User.class);
            request.getSession().setAttribute("user", user);
            return true;
        }
        //跳转到单点登录界面
        state = Const._SSO_LOGIN + Const.UNDERLINE + RandomUtil.getUUID();
        request.getSession().setAttribute(state, uri);
        String redirectUrl = buildAuthCodeUrl(uri, state);
        response.sendRedirect(redirectUrl);
        return false;
    }

    后面把前端vue请求后台的登录接口方式直接用

    window.location.href=this.$api.config.baseUrl+"/system/user/login"

    之后前端访问系统,可以直接跳转到单点登录页面。但是当我输完账号和密码点击登录后回跳到系统,发现所有的请求数据接口都无法正常访问,debug发现所有的请求都没带用户信息,被拦截器识别为未登录,所有请求无法通过。

    为什么我明明登录了呀,拦截器也设置了用户信息到session啊,怎么cookies那就没了呢?再次发起请求,发现每次请求的JsessionId都不一样,查了很多资料,发现是需要在前端加一个允许带认证信息的配置

    axios.defaults.withCredentials=true;

    后台也需要做一个相应的配置allowCredentials(true);

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedHeaders("*")
                        .allowedMethods("*")
                        .allowedOrigins("*").allowCredentials(true);
            }
        };
    }

    加完这个配置之后,重新执行一遍操作流程,发现登录之后能正常跳转到系统,页面数据也展示正常。

    正当我以为大功告成的时候,突然点到一个页面又无法正常显示数据,好纳闷啊,赶紧F12,发现一个之前没见过的请求方式,OPTIONS请求,原来这个请求方式明明是POST呀,怎么就变成了OPTIONS了呢?于是我有点了其他几个POST的请求,发现都变成了OPTIONS请求,一脸懵逼的我赶紧查了一下OPTIONS请求的资料,网上说OPTIONS请求叫做“预检查请求”,就是在你的正式请求执行之前,浏览器会先发起预检查请求,预检查请求通过了,才能执行正式请求。看完恍然大悟,原来OPTIONS被拦截了,所以没法再执行我的POST的请求啊,那我直接让预检查请求通过就好了。只要在拦截器中加一个这个判断就好了

    //option预检查,直接通过请求
    if ("OPTIONS".equals(request.getMethod())){
        return true;
    }

    这样拦截器发现请求是预检查请求就直接通过,就可以执行接下来的POST的请求了。

    转载请注明:呆萌钟 » vue+springboot前后端分离实现单点登录跨域问题处理

     

    展开全文
  • 单点登录跨域碰上SameSite问题

    千次阅读 2020-08-26 13:45:01
    单点登录跨域碰上SameSite问题项目场景:问题描述:原因分析:解决方案:这里还遇到一个问题:headers一直是空? 项目场景: 两个项目:auth_webapp、admin_webapp 单点登录流程: 点击登录请求:/auth/api/login?...

    项目场景:

    两个项目:auth_webapp、admin_webapp
    单点登录流程:

    1. 点击登录请求:/auth/api/login?name=xxx&password=xxx,auth服务器用jwt处理后获得token,将token写入cookie,并返回token。
    2. 前端请求:/admin/api/getLoginVo,admin服务器返回提示未登录。
    3. 前端再次请求:/auth/api/login,此时不带用户名和密码,只是将1中的cookie带入request。
    4. 前端拿到3中的token请求:/admin/api/login?token=xxx,admin服务器验证token,返回登录结果。
    5. 前端再次请求:/admin/api/getLoginVo,admin服务器返回登录用户信息。

    问题描述:

    最近发现个别用户总是登录不了,通过分析请求发现,在流程3时,cookie没有写入request请求中,导致再次获取token失败,从而流程断裂。


    原因分析:

    百度SameSite可以知道是浏览器用来限制第三方cookie的,具体可以参考

    http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html

    正是由于Chrome更改了默认的SameSite属性,导致了在流程3时,不能将cookie写入request中。


    解决方案:

    既然明白了是SameSite属性导致了跨域cookie不能被使用,那么我们就将cookie的SameSite属性改成最低级的就可以解决这个问题了。在auth服务器中添加Interceptor:

    public class SameSiteInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            Collection<String> headers = response.getHeaders(HttpHeaders.SET_COOKIE);
            boolean firstHeader = true;
            for (String header : headers) { // there can be multiple Set-Cookie attributes
                response.addHeader(HttpHeaders.SET_COOKIE, String.format("%s; %s", header, "SameSite=None; Secure;"));
            }
        }
    }
    

    这里还遇到一个问题:headers一直是空?

    之前auth_webapp的容器使用的是undertow,headers一直获取不到,之后切换成了tomcat又可以了。

    源码分析:
    undertow的HttpServletResponse实现类是io.undertow.servlet.spec.HttpServletResponseImpl,源码分析:

    public final class HttpServletResponseImpl implements HttpServletResponse {
    
        private final HttpServerExchange exchange;
        private final ServletContextImpl originalServletContext;
        private volatile ServletContextImpl servletContext;
    
    	//此处省略无用代码
    	
        @Override
        public void addCookie(final Cookie cookie) {
            if (insideInclude) {
                return;
            }
            final ServletCookieAdaptor servletCookieAdaptor = new ServletCookieAdaptor(cookie);
            if (cookie.getVersion() == 0) {
                servletCookieAdaptor.setVersion(servletContext.getDeployment().getDeploymentInfo().getDefaultCookieVersion());
            }
            exchange.setResponseCookie(servletCookieAdaptor);
        }
    }
    

    从源码可以看出,addCookie方法其实是将cookie保存在了exchange对象里面。而没有放入header中。对比而言,我们可以看看tomcat中的HttpServletResponse实现类org.apache.catalina.connector.ResponseFacade

        @Override
        public void addCookie(Cookie cookie) {
    
            if (isCommitted()) {
                return;
            }
    
            response.addCookie(cookie);
    
        }
    

    继续追org.apache.catalina.connector.Response.addCookie()

        /**
         * Add the specified Cookie to those that will be included with
         * this Response.
         *
         * @param cookie Cookie to be added
         */
        @Override
        public void addCookie(final Cookie cookie) {
    
            // Ignore any call from an included servlet
            if (included || isCommitted()) {
                return;
            }
    
            cookies.add(cookie);
    
            String header = generateCookieString(cookie);
            //if we reached here, no exception, cookie is valid
            // the header name is Set-Cookie for both "old" and v.1 ( RFC2109 )
            // RFC2965 is not supported by browsers and the Servlet spec
            // asks for 2109.
            addHeader("Set-Cookie", header, getContext().getCookieProcessor().getCharset());
        }
    
    
    展开全文
  • 最近公司要采用单点登录技术,又不想和传统的单点登录一样,比如说,A系统登录了,再进B系统会直接登录,但是这里有个不好的体验度就是B系统会有一个内部跳转的过程,会重定向到认证中心,再回来。所有这次我们就是...

           最近公司要采用单点登录技术,又不想和传统的单点登录一样,比如说,A系统登录了,再进B系统会直接登录,但是这里有个不好的体验度就是B系统会有一个内部跳转的过程,会重定向到认证中心,再回来。所以这次我们就是要攻克这个跳转的过程,提高这个用户体验度。

     

           废话不多说,开整~~!

     

           先上一个架构时序图

            这个方案网上也有大佬用过,算是借鉴了部分思路,但是正好这块是自己以前接触过的一个技术点,所以才想到用这种方式。

     

    a.html页面的代码~~~~(我是后端原谅我写的丑~~~)

    <!DOCTYPE html>
    <html>
    
    <head>
    
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    
        <title>Guns</title>
          <!-- 全局js -->
        <script src="js/jquery-3.3.1.min.js"></script>
        <script src="js/jquery.cookie.js" type="text/javascript"></script>
    </head>
    
    <body class="gray-bg">
    
        <p>这是主页</p>
        <iframe src="http://www.bb.com:8083/sso/b.html" style="height: 100px;width: 100px;display: block;"></iframe>
       
    
    
    </body>
    <script  type="text/javascript">
        window.onload = () =>{
            var data=JSON.stringify({
                msg:'msg',
                token:'331'
            })
            document.getElementsByTagName('iframe')[0].contentWindow.postMessage(data,'*');
        }
    
        window.addEventListener('message',function(e){
    
            // 有消息从子级传来时 存贮 tokenData
    //        if(e.source!=window.parent) return;
            console.log("==========a===========")
            //e.data即是我们从A传来的数据 这里使用localStorage进行存贮(请勿使用sessionStorage)
            localStorage.setItem("tokenData",e.data);
            console.log(e.data);
    
    
        },false);
    </script>
    </html>
    

    b.html页面的代码 (同上)

    <!DOCTYPE html>
    <html>
    
    <head>
    
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    
        <title>Guns</title>
        
        <script src="js/jquery-3.3.1.min.js"></script>
    
        <script src="js/jquery.cookie.js" type="text/javascript"></script>
    </head>
    
    <body class="gray-bg">
    
        <p>这是b页</p>
    
    </body>
    <script type="text/javascript">
     
        console.log(localStorage.getItem("tokenData"));
        
        window.addEventListener('message',function(e){
    		console.log("==========b===========")
            // 有消息从父级传来时 存贮 tokenData
            if(e.source!=window.parent) return;
    
            //e.data即是我们从A传来的数据 这里使用localStorage进行存贮(请勿使用sessionStorage)
            localStorage.setItem("tokenData",e.data);
            console.log(e.data);
            var child = JSON.stringify(localStorage.getItem("tokenData"));
            window.parent.postMessage(child, '*');
        },false);
    </script>
    </html>
    

    当然直接这样可能是不行的,还要配置hosts哦

    127.0.0.1 www.aa.com
    127.0.0.1 www.bb.com
     

    然后部署起来就行啦。

    访问测试

    可以互相通信,单点登录的策略就能实现了,加油!奥力给~~!

    源码下载:https://download.csdn.net/download/lj88811498/12919806

    展开全文
  • 单点登录系统总结 关于登录 一、登录 1、当用户点击登录的时候,把当前页面的url用参数传递到登录页面 2、用户成功登录,生成token,保存到redis中(service层),key为token,value为用户对象信息 3、同时将用户token...

    单点登录系统总结

    关于登录
    一、登录
    1、当用户点击登录的时候,把当前页面的url用参数传递到登录页面
    2、用户成功登录,生成token,保存到redis中(service层),key为token,value为用户对象信息
    3、同时将用户token和用户对象信息存入到cookie中。注意将密码进行MD5加密处理
    4、登录成功后,通过判断是否有returnUrl来返回到用户登录前的页面
    5、这里是做了如下的处理:
    function login(query) {
    return location.href = “http://localhost:8084/login?ReturnUrl=http://localhost:8082/search.html?q=”+query;
    }

    即每个模块都会在点击登录的方法中写上当前的服务器域名和端口号,并将当前页面信息使用参数传递到后台controller
    具体参数是在页面使用参数传到js文件中。(否则取不到页面信息)
    当然首页登录就不需要做特殊处理了。
    

    6、在后台获取到returnUrl后,存入到model中。返回给前台。
    前台如果收到了returnUrl不为空,那么跳转到returnUrl页面

    二、跨域
    1、当用户成功登录后,在cookie和redis中都有对应的token,当用户每次访问其他模块,都会发送一个ajax的跨域请求来取出token
    2、取token的前提是cookie中有token(即用户登录过),如果cookie中有,redis没有,那么表示用户登录过期
    3、当cookie中的token和redis中的token匹配,那么可以认为用户正常SSO登录访问。
    2、原理:发送ajax跨域请求,需要使用jsonp,传递一个callback参数,用来表示是跨域请求。使用下面方法来返回跨域信息
    if(StringUtils.isNotBlank(callback)){
    //请求中包含了callback,表示是一个跨域请求
    MappingJacksonValue mappingJacksonValue=new MappingJacksonValue(result);
    mappingJacksonValue.setJsonpFunction(callback);
    return mappingJacksonValue;
    }

    *:cookie中设置token的时候进行了跨域处理。(老师写的,具体详情未知)
    

    跨域获取token:
    public JDResult getUserByToken(String token) {
    String json=jedisClient.get(USER_SESSION+token);
    if(StringUtils.isBlank(json)){
    //表示用户登录过期,redis中没有,token有
    return JDResult.bind(400, “用户登录过期”);
    }
    //重置session时间
    jedisClient.expire(USER_SESSION+token, SESSION_EXPIRE);
    //将json对象转换成user对象
    TbUser user=JsonUtils.jsonToPojo(json, TbUser.class);
    return JDResult.ok(user);
    }

    //对于spring4.1或以上版本才能使用
    @RequestMapping(value="/user/token/{token}",method=RequestMethod.GET)
    @ResponseBody
    public Object getUserByToken(@PathVariable("token") String token,String callback){
    	JDResult result = userService.getUserByToken(token);
    	if(StringUtils.isNotBlank(callback)){
    		//请求中包含了callback,表示是一个跨域请求
    		MappingJacksonValue mappingJacksonValue=new MappingJacksonValue(result);
    		mappingJacksonValue.setJsonpFunction(callback);
    		return mappingJacksonValue;
    	}
    	return result;
    } 
    
    //对于spring4.1以下版本这样获取token
    @RequestMapping(value="/user/token/{token}",method=RequestMethod.GET)
    @ResponseBody
    public Object getUserByToken(@PathVariable("token") String token,String callback){
    	JDResult result = userService.getUserByToken(token);
    	if(StringUtils.isNotBlank(callback)){
    		//请求中包含了callback,表示是一个跨域请求
    		return callback+"("+JsonUtils.objectToJson(result)+")";
    	}
    	return result;
    }
    

    三、注销
    1、注销的a链接是在用户登录后,每次访问模块的时候通过ajax动态生成的,那么需要给这个a链接绑定一个事件
    var username=result.data.username;
    var html=username+",欢迎来到京东![退出]";
    $("#loginbar").html(html);
    $("#sa").bind(‘click’,function(){

    *:注意,这里用到了bind,没有使用on,发现jquery版本低的时候不可以使用on来绑定事件。
    之前没有用bind,而是直接写的 …发现报错。考虑这个事件没有被注册和加载到内存中
    因此使用了bind来绑定事件

    2、当点击注销的时候,发现ajax跨域请求,用到jsonp,和callback参数,返回状态码
    KaTeX parse error: Expected '}', got 'EOF' at end of input: …0){ var que=("#que").val();
    var html=“您好,欢迎来到京东[登录] [免费注册]”;
    $("#loginbar").html(html);
    }
    }

    *:注意:这里用到了一个隐藏域,因为考虑到点击注销的时候,又可以再次点击登录,而点登录的时候是需要页面参数的,
    因为将页面关键参数信息通过隐藏域放入到了一个input里,然后通过jquery获取到隐藏域中的值
    注意:方法中login(""+que+""),需要用到转义字符",之前这样写: login(’"+que"’)方法报错,不被识别。
    具体原因是不是因为引号,未知。
    首页注销发送ajax请求,不做特殊处理。其他域注销的时候,需要获取到页面参数。(因为点登录的时候需要用)

    跨域注销:
    public JDResult logout(String token) {
    try {
    jedisClient.expire(USER_SESSION+token, 0);
    return JDResult.ok();
    } catch (Exception e) {
    e.printStackTrace();
    return JDResult.bind(400, “退出登录失败”);
    }
    }

    @RequestMapping(value="/user/logout/{token}",method=RequestMethod.GET)
    @ResponseBody
    public Object logout(@PathVariable("token") String token,String callback,
    		HttpServletRequest request,HttpServletResponse response){
    	JDResult jdResult = userService.logout(token);
    	CookieUtils.deleteCookie(request, response, SESSION_TOKEN);
    	if(StringUtils.isNotBlank(callback)){
    		//请求中包含了callback,表示是一个跨域请求
    		MappingJacksonValue mappingJacksonValue=new MappingJacksonValue(jdResult);
    		mappingJacksonValue.setJsonpFunction(callback);
    		return mappingJacksonValue;
    	}
    	return jdResult;
    } 
    
    package org.java.common.utils;
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    
    /**
     * 
     * Cookie 工具类
     *
     */
    public final class CookieUtils {
    
        /**
         * 得到Cookie的值, 不编码
         * 
         * @param request
         * @param cookieName
         * @return
         */
        public static String getCookieValue(HttpServletRequest request, String cookieName) {
            return getCookieValue(request, cookieName, false);
        }
    
        /**
         * 得到Cookie的值,
         * 
         * @param request
         * @param cookieName
         * @return
         */
        public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
            Cookie[] cookieList = request.getCookies();
            if (cookieList == null || cookieName == null) {
                return null;
            }
            String retValue = null;
            try {
                for (int i = 0; i < cookieList.length; i++) {
                    if (cookieList[i].getName().equals(cookieName)) {
                        if (isDecoder) {
                            retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
                        } else {
                            retValue = cookieList[i].getValue();
                        }
                        break;
                    }
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return retValue;
        }
    
        /**
         * 得到Cookie的值,
         * 
         * @param request
         * @param cookieName
         * @return
         */
        public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
            Cookie[] cookieList = request.getCookies();
            if (cookieList == null || cookieName == null) {
                return null;
            }
            String retValue = null;
            try {
                for (int i = 0; i < cookieList.length; i++) {
                    if (cookieList[i].getName().equals(cookieName)) {
                        retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
                        break;
                    }
                }
            } catch (UnsupportedEncodingException e) {
            	 e.printStackTrace();
            }
            return retValue;
        }
    
        /**
         * 设置Cookie的值 不设置生效时间默认浏览器关闭即失效,也不编码
         */
        public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
                String cookieValue) {
            setCookie(request, response, cookieName, cookieValue, -1);
        }
    
        /**
         * 设置Cookie的值 在指定时间内生效,但不编码
         */
        public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
                String cookieValue, int cookieMaxage) {
            setCookie(request, response, cookieName, cookieValue, cookieMaxage, false);
        }
    
        /**
         * 设置Cookie的值 不设置生效时间,但编码
         */
        public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
                String cookieValue, boolean isEncode) {
            setCookie(request, response, cookieName, cookieValue, -1, isEncode);
        }
    
        /**
         * 设置Cookie的值 在指定时间内生效, 编码参数
         */
        public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
                String cookieValue, int cookieMaxage, boolean isEncode) {
            doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, isEncode);
        }
    
        /**
         * 设置Cookie的值 在指定时间内生效, 编码参数(指定编码)
         */
        public static void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName,
                String cookieValue, int cookieMaxage, String encodeString) {
            doSetCookie(request, response, cookieName, cookieValue, cookieMaxage, encodeString);
        }
    
        /**
         * 删除Cookie带cookie域名
         */
        public static void deleteCookie(HttpServletRequest request, HttpServletResponse response,
                String cookieName) {
            doSetCookie(request, response, cookieName, "", -1, false);
        }
    
        /**
         * 设置Cookie的值,并使其在指定时间内生效
         * 
         * @param cookieMaxage cookie生效的最大秒数
         */
        private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
                String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {
            try {
                if (cookieValue == null) {
                    cookieValue = "";
                } else if (isEncode) {
                    cookieValue = URLEncoder.encode(cookieValue, "utf-8");
                }
                Cookie cookie = new Cookie(cookieName, cookieValue);
                if (cookieMaxage > 0)
                    cookie.setMaxAge(cookieMaxage);
                if (null != request) {// 设置域名的cookie
                	String domainName = getDomainName(request);
                	//System.out.println(domainName);
                    if (!"localhost".equals(domainName)) {
                    	cookie.setDomain(domainName);
                    }
                }
                cookie.setPath("/");
                response.addCookie(cookie);
            } catch (Exception e) {
            	 e.printStackTrace();
            }
        }
    
        /**
         * 设置Cookie的值,并使其在指定时间内生效
         * 
         * @param cookieMaxage cookie生效的最大秒数
         */
        private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,
                String cookieName, String cookieValue, int cookieMaxage, String encodeString) {
            try {
                if (cookieValue == null) {
                    cookieValue = "";
                } else {
                    cookieValue = URLEncoder.encode(cookieValue, encodeString);
                }
                Cookie cookie = new Cookie(cookieName, cookieValue);
                if (cookieMaxage > 0)
                    cookie.setMaxAge(cookieMaxage);
                if (null != request) {// 设置域名的cookie
                	String domainName = getDomainName(request);
                	System.out.println(domainName);
                    if (!"localhost".equals(domainName)) {
                    	cookie.setDomain(domainName);
                    }
                }
                cookie.setPath("/");
                response.addCookie(cookie);
            } catch (Exception e) {
            	 e.printStackTrace();
            }
        }
    
        /**
         * 得到cookie的域名
         */
        private static final String getDomainName(HttpServletRequest request) {
            String domainName = null;
    
            String serverName = request.getRequestURL().toString();
            if (serverName == null || serverName.equals("")) {
                domainName = "";
            } else {
                serverName = serverName.toLowerCase();
                serverName = serverName.substring(7);
                final int end = serverName.indexOf("/");
                serverName = serverName.substring(0, end);
                final String[] domains = serverName.split("\\.");
                int len = domains.length;
                if (len > 3) {
                    // www.xxx.com.cn
                    domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
                } else if (len <= 3 && len > 1) {
                    // xxx.com or xxx.cn
                    domainName = "." + domains[len - 2] + "." + domains[len - 1];
                } else {
                    domainName = serverName;
                }
            }
    
            if (domainName != null && domainName.indexOf(":") > 0) {
                String[] ary = domainName.split("\\:");
                domainName = ary[0];
            }
            return domainName;
        }
    
    }
    
    
    展开全文
  • 单点登录跨域问题

    2020-05-25 09:07:25
    我们项目集成别人的录平台,在我们发送请求对方响应重定向我们时,浏览器F12报跨域问题。 Access to XMLHttpRequest at 'http://对方IP:8080/cas/login?service=http%3A%2F%2F我的IP%3A8899%2Fepcs%2Femis%2...
  • config.withCredentials = true//在跨域请求时携带用户凭证cookie 前端设置withCredentials = true后,跨域请求会被拦截,报错 解决: 后端配置: Access-Control-Allow-Credentials为true Access-Control-Allow-...
  • 完全跨域单点登录, 适用于java语言开发, demo中展示了单点登陆的原理, 可用于理论学习
  • SSO单点登录技术,其中有一种就是通过js的跨域设置cookie来达到单点登录目的的,下面就已京东商城为例来解释下跨域设置cookie的过程涉及的关键知识点:1、跨域redirect实例:test.html跟test.html同域名下的test....
  • SSO跨域单点登录Demo

    2018-01-19 14:57:08
    自己写的一个SSO跨域单点登录Demo,直接使用Eclipse导入即可使用,压缩包中附有自己总结的详细的使用说明和跨域登录原理讲解,感兴趣的朋友可以看一下。
  • 最近在研究SSO单点登录技术,其中有一种就是通过js的跨域设置cookie来达到单点登录目的的,下面就已京东商城为例来解释下跨域设置cookie的过程 涉及的关键知识点: 1、jQueryajax跨域重定向,要理ajax解跨域重定向,...
  • 单点登录的cookie跨域设置

    千次阅读 2018-11-20 17:11:40
    单点登录的cookie跨域设置 单点登录原理 当公司有好多系统存在并运行时候,用户每个系统使用之前都需要登录认证,操作起来就比较重复,用户体验感不好,然后就衍生出来单点登录.如下图所示: 单点登录: 英文名(Single ...
  • JavaWeb跨域单点登录

    2018-08-06 14:44:30
    1、该代码,使用maven构建的模块化项目工程,ssm框架,直接import --> existing maven projects 即可 ...4、单点登录教程可以参考 https://blog.csdn.net/weixin_42686388/article/details/81299609
  • SSO跨域单点登录原理分析及实现 什么是单点登录 什么是跨域单点登录 跨域单点登录原理 简单的跨域单点登录代码实现
  • cas跨域单点登录原理

    万次阅读 热门讨论 2017-04-17 21:12:43
    cas跨域单点登录原理
  • 使用JWT实现单点登录(完全跨域方案)

    万次阅读 多人点赞 2018-09-10 15:57:56
    授权:这是最常见的使用场景,解决单点登录问题。因为JWT使用起来轻便,开销小,服务端不用记录用户状态信息(无状态),所以使用比较广泛; 信息交换:JWT是在各个服务之间安全传输信息的好方法。因为JWT可以签名...
  • 什么是单点登录跨域
  • java跨域单点登录实现

    2021-01-28 10:05:08
    跨域单点登录实现项目代码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,126
精华内容 13,650
关键字:

单点登录跨域