当前位置: 移动技术网 > IT编程>开发语言>.net > SSO集成方案[随笔]

SSO集成方案[随笔]

2019年04月13日  | 移动技术网IT编程  | 我要评论

甲子蕙,张君龙28秒ko泰拳王,异界海盗王下载

看这个方案之前,先说明下为什么要加入sso,以防对大家产生不好的影响。我们产品使用传统winform+db服务+db存储方式开发,一群老菜帮子开发,以传统的datatble做数据传递,很多年了未有变化。

然后我来了,感觉我这个老菜帮子都受不了这种开发,然后下定决心,作了一些封装,看起来有点像orm的感觉了,并决定加入嵌入bs页面,美化界面,并补充winform在图表功能方面的短板。

然后就造成了各bs模块分别嵌入到cs不同的页面中,并且各bs模块中有涉及到对业务的操作。很危险!因为在网页中可以直接打开各bs模块视图,无需登录,无需验证等。针对这种情况,sso需求由此而来…

 

目标:

  1.bs模块统一使用单点登录,不能没有限制就使用业务系统

  2.cs端嵌入bs时自动模拟sso,实现可以免登录使用页面

 

下文sso科普是复制不知道谁的博文的,具体是谁忘了,在此说明下

sso整体流程图:

 

 

 

sso分为sso-serversso-client两个部分,sso-client可以是多个的,即各个需要单点登录的client

sso-server

sso-server主要负责用户登录、注销、为sso-client分配token、验证token的工作。

sso-server分配token

为sso-client分配token的部分,在sso-client请求sso受信页面的时候,检查sso-server是否登录,如果没有登录则跳转到sso-server的登录页面,如果已登录,则执行分配token的代码,在分配完成以后将tokenid作为参数添加到returnurl中,并跳转到returnurl。

当完成token分配之后,页面将带有token的参数跳转到sso-client页面,并在sso-client的cookie中添加token值,在以后的每次请求中,sso-client通过调用sso-server的服务来验证token的合法性。

validatetoken用来验证tokenid的合法性,keeptoken用来保持token不会过期。

sso-client通过调用validate验证token,并得到当前的登录用户信息。

sso-client

sso-client作为受信系统来存在的,它自己没有认证系统,只能通过sso-server来完成用户身份认证的工作。

当用户请求sso-client的受保护资源时,sso-client会首先是否有tokenid,如果存在tokenid,则调用sso-server的接口来验证这个tokenid是否合法;

验证成功以后将会返回ssotoken的实例,里面包含已登录的用户信息

 

科普后动手:

mvc.sso.service:mvc+redis,mvc实现sso-server的所有功能,存储和时效使用redis管理,并使用redis共享session

主要代码:

     /// <summary>
        /// 验证是否包含该token,并返回信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        [httppost]
        public string validatetoken(string key)
        {
            //var token = tokensmanager.gettoken(key);

            try
            {
                mytoken token = new mytoken();
                token.validatetoken = false;

                if (boolvalidatetoken(key))
                {
                    token.user = redis.stringget<users>(key);
                    token.validatetoken = true;
                }

                return jsonconvert.serializeobject(token);
            }
            catch (exception ex)
            {
                throw new exception("validatetoken:" + ex.message);
            }
        }


     /// <summary>
        /// 登录
        /// </summary>
        /// <param name="name"></param>
        /// <param name="password"></param>
        /// <param name="backurl"></param>
        /// <returns></returns>
        [httppost]
        public string login(string name, string password, string backurl)
        {
            try
            {
                mymsg msg = new mymsg();
                //tokenkey
                byte[] byts = system.text.encoding.default.getbytes(string.format("{0},{1}", name, password));
                var key = convert.tobase64string(byts);
                //判断是否tokenids是否已存在该用户,不存在则判断登录,添加到token
                if (!boolvalidatetoken(key))
                {
                    var user = userbll.getuser(name, password);
                    if (user == null)
                    {
                        msg.islogined = false;
                        msg.msg = "用户名或密码错误,登录失败!";
                    }
                    msg.islogined = true;
                    //并添加到全局变量中
                    //tokensmanager.addtoken(key, user);
                    session["token"] = key;
                    redis.stringset<users>(key, user);
                }

                session["token"] = key;
                response.cookies.add(new httpcookie("ctoken", key));
                if (!string.isnullorempty(backurl))
                {
                    var url = backurl + "?token=" + key;
                    //response.redirect(backurl + "?token=" + key, true);//生成一个tokenid 发放到客户端
                    msg.backurl = url;
                }
                msg.msg = "欢迎您:" + name;
                return jsonconvert.serializeobject(msg);
            }
            catch (exception ex)
            {
                throw;
            }
        }

 

bs端mvc-client集成方案

mvc集成sso方式为添加过滤器,并在需要添加sso验证的控制器上添加上该过滤器

主要代码:

public override void onactionexecuting(actionexecutingcontext filtercontext)
        {
            base.onactionexecuting(filtercontext);

            try
            {
                bool islogined = false;//登录标志
                var ctoken = filtercontext.httpcontext.request.cookies["ctoken"];
                var token = filtercontext.httpcontext.request["token"];
                var sessionkey = httpcontext.current.session["token"];
                if (token != null || sessionkey != null || ctoken != null)
                {//ewfuc2hplge=
                    token = token ?? sessionkey.tostring() ?? ctoken.value;
                    var data = new { key = token };
                    //如果token不为空则去服务验证token是否有效
                    httpcontent httpcontent = new stringcontent(jsonconvert.serializeobject(data));
                    httpcontent.headers.contenttype = new mediatypeheadervalue("application/json");
                    var httpclient = new httpclient();
                    var responsejson = httpclient.postasync(ssourl + "/validatetoken", httpcontent)
                        .result.content.readasstringasync().result;
                    var mytoken = jsonconvert.deserializeobject<jh_oemr_model.mytoken>(responsejson);
                    if (mytoken.validatetoken)
                    {
                        islogined = true;
                    }
                }

                if (!islogined)
                    filtercontext.httpcontext.response.redirect(ssourl+"?backurl=" + filtercontext.httpcontext.request.url, true);
            }
            catch (exception ex)
            {
                filtercontext.httpcontext.response.write("aaaaa"+ex.message.tostring());
                throw;
            }
        }

cs端集成sso:

cs端加载bs页面时,先判断是否模拟登录,如未登录,模拟登录,然后访问bs端网址带上token即可

主要代码:

private static void loginsso()
        {
            var data = new { name = uname, password = upwd, backurl = string.empty };
            httpcontent httpcontent = new stringcontent(jsonconvert.serializeobject(data));
            httpcontent.headers.contenttype = new mediatypeheadervalue("application/json");
            var httpclient = new httpclient();
            var responsejson = httpclient.postasync(ssourl+"/login", httpcontent)
                .result.content.readasstringasync().result;
            var mytoken = jsonconvert.deserializeobject<mymsg>(responsejson);
            if (mytoken.islogined)
            {
                isloginedsso = true;
            }
        }

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网