Пример #1
0
        /// <summary>验证用户身份</summary>
        /// <remarks>
        /// 子系统需要验证访问者身份时,引导用户跳转到这里。
        /// 用户登录完成后,得到一个独一无二的code,并跳转回去子系统。
        /// </remarks>
        /// <param name="client_id">应用标识</param>
        /// <param name="redirect_uri">回调地址</param>
        /// <param name="response_type">响应类型。默认code</param>
        /// <param name="scope">授权域</param>
        /// <param name="state">用户状态数据</param>
        /// <returns></returns>
        public virtual String Authorize(String client_id, String redirect_uri, String response_type = null, String scope = null, String state = null)
        {
            var log = new AppLog
            {
                Action  = nameof(Authorize),
                Success = true,

                ClientId     = client_id,
                RedirectUri  = redirect_uri,
                ResponseType = response_type,
                Scope        = scope,
                State        = state
            };

            try
            {
                //if (!response_type.EqualIgnoreCase("code")) throw new NotSupportedException(nameof(response_type));

                var app = App.FindByName(client_id);
                if (app != null)
                {
                    log.AppId = app.ID;
                }

                app       = Auth(client_id, null);
                log.AppId = app.ID;

                // 验证回调地址
                if (!app.ValidCallback(redirect_uri))
                {
                    throw new XException("回调地址不合法 {0}", redirect_uri);
                }

                // 统计次数
                app.Auths++;
                app.LastAuth = DateTime.Now;
                app.SaveAsync(5_000);

                if (Log != null)
                {
                    WriteLog("Authorize client_id={0} redirect_uri={1} response_type={2}", client_id, redirect_uri, response_type);
                }
            }
            catch (Exception ex)
            {
                log.Success = false;
                log.Remark  = ex.GetTrue()?.Message;

                throw;
            }
            finally
            {
                log.Insert();
            }

            return(log.ID + "");
        }
Пример #2
0
        /// <summary>密码式获取令牌</summary>
        /// <param name="sso"></param>
        /// <param name="client_id">应用标识</param>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public virtual TokenInfo GetAccessTokenByPassword(OAuthServer sso, String client_id, String username, String password, String ip)
        {
            var log = new AppLog
            {
                Action  = "Password",
                Success = true,

                ClientId     = client_id,
                ResponseType = "password",
                CreateIP     = ip,
            };

            try
            {
                var app = sso.Auth(client_id, null);
                log.AppId = app.ID;

                // 不能使用 ManagerProvider,它会写cookie
                //var user = Provider.Login(username, password, false);
                var user = XCode.Membership.User.Login(username, password, false);
                if (user == null)
                {
                    throw new XException("用户{0}验证失败", username);
                }

                var token = sso.CreateToken(app, user.Name, null, $"{client_id}#{user.Name}");
                //var token = sso.CreateToken(app, user.Name, new
                //{
                //    userid = user.ID,
                //    usercode = user.Code,
                //    nickname = user.DisplayName,
                //});
                //var token = sso.CreateToken(app, user.Name, GetUserInfo(null, null, user));
                //token.Scope = "basic,UserInfo";

                log.AccessToken  = token.AccessToken;
                log.RefreshToken = token.RefreshToken;

                log.CreateUser = user.Name;
                log.Scope      = token.Scope;

                return(token);
            }
            catch (Exception ex)
            {
                log.Success = false;
                log.Remark  = ex.GetTrue()?.Message;

                throw;
            }
            finally
            {
                log.Insert();
            }
        }
Пример #3
0
        /// <summary>凭证式获取令牌</summary>
        /// <param name="sso"></param>
        /// <param name="client_id">应用标识</param>
        /// <param name="client_secret">密钥</param>
        /// <param name="refresh_token">刷新令牌</param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public virtual TokenInfo RefreshToken(OAuthServer sso, String client_id, String client_secret, String refresh_token, String ip)
        {
            var log = new AppLog
            {
                Action  = "RefreshToken",
                Success = true,

                ClientId     = client_id,
                ResponseType = "refresh_token",
                CreateIP     = ip,
            };

            try
            {
                var app = App.FindByName(client_id);
                if (app != null)
                {
                    log.AppId = app.ID;
                }

                app       = sso.Auth(client_id, client_secret);
                log.AppId = app.ID;

                var name = sso.Decode(refresh_token);
                var ss   = name.Split("#");
                if (ss.Length != 2 || ss[0] != client_id)
                {
                    throw new Exception("非法令牌");
                }

                // 使用者标识保持不变
                var code  = ss[1];
                var token = sso.CreateToken(app, code, null, $"{client_id}#{code}");

                log.AccessToken  = token.AccessToken;
                log.RefreshToken = token.RefreshToken;

                log.CreateUser = code;
                log.Scope      = token.Scope;

                return(token);
            }
            catch (Exception ex)
            {
                log.Success = false;
                log.Remark  = ex.GetTrue()?.Message;

                throw;
            }
            finally
            {
                log.Insert();
            }
        }
Пример #4
0
        /// <summary>凭证式获取令牌</summary>
        /// <param name="sso"></param>
        /// <param name="client_id">应用标识</param>
        /// <param name="client_secret">密钥</param>
        /// <param name="username">用户名。可以是设备编码等唯一使用者标识</param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public virtual TokenInfo GetAccessTokenByClientCredentials(OAuthServer sso, String client_id, String client_secret, String username, String ip)
        {
            var log = new AppLog
            {
                Action  = "ClientCredentials",
                Success = true,

                ClientId     = client_id,
                ResponseType = "client_credentials",
                CreateIP     = ip,
            };

            try
            {
                var app = App.FindByName(client_id);
                if (app != null)
                {
                    log.AppId = app.ID;
                }

                app       = sso.Auth(client_id, client_secret, ip);
                log.AppId = app.ID;

                // 验证应用能力
                var scopes = app.Scopes?.Split(",");
                if (scopes == null || !"client_credentials".EqualIgnoreCase(scopes))
                {
                    throw new InvalidOperationException($"应用[{app}]没有使用client_credentials客户端凭证的能力!");
                }

                var code  = !username.IsNullOrEmpty() ? username : ("_" + Rand.NextString(7));
                var token = sso.CreateToken(app, code, null, $"{client_id}#{code}");
                //token.Scope = "basic,UserInfo";

                log.AccessToken  = token.AccessToken;
                log.RefreshToken = token.RefreshToken;

                log.CreateUser = code;
                log.Scope      = token.Scope;

                return(token);
            }
            catch (Exception ex)
            {
                log.Success = false;
                log.Remark  = ex.GetTrue()?.Message;

                throw;
            }
            finally
            {
                log.Insert();
            }
        }
Пример #5
0
        /// <summary>凭证式获取令牌</summary>
        /// <param name="sso"></param>
        /// <param name="client_id">应用标识</param>
        /// <param name="client_secret">密钥</param>
        /// <param name="username">用户名。可以是设备编码等唯一使用者标识</param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public virtual TokenInfo GetAccessTokenByClientCredentials(OAuthServer sso, String client_id, String client_secret, String username, String ip)
        {
            var log = new AppLog
            {
                Action  = "ClientCredentials",
                Success = true,

                ClientId     = client_id,
                ResponseType = "client_credentials",
                CreateIP     = ip,
            };

            try
            {
                var app = sso.Auth(client_id, client_secret);
                log.AppId = app.ID;

                var code  = !username.IsNullOrEmpty() ? username : ("_" + Rand.NextString(7));
                var token = sso.CreateToken(app, code, $"{client_id}#{code}");
                //token.Scope = "basic,UserInfo";

                log.AccessToken  = token.AccessToken;
                log.RefreshToken = token.RefreshToken;

                log.CreateUser = code;
                log.Scope      = token.Scope;

                return(token);
            }
            catch (Exception ex)
            {
                log.Success = false;
                log.Remark  = ex.GetTrue()?.Message;

                throw;
            }
            finally
            {
                log.Insert();
            }
        }
Пример #6
0
        /// <summary>密码式获取令牌</summary>
        /// <param name="sso"></param>
        /// <param name="client_id">应用标识</param>
        /// <param name="username">用户名</param>
        /// <param name="password">密码。支持md5密码,以md5#开头</param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public virtual TokenInfo GetAccessTokenByPassword(OAuthServer sso, String client_id, String username, String password, String ip)
        {
            var log = new AppLog
            {
                Action  = "Password",
                Success = true,

                ClientId     = client_id,
                ResponseType = "password",
                CreateIP     = ip,
            };

            try
            {
                var app = sso.Auth(client_id, null, ip);
                log.AppId = app.ID;

                // 验证应用能力
                var scopes = app.Scopes?.Split(",");
                if (scopes == null || !"password".EqualIgnoreCase(scopes))
                {
                    throw new InvalidOperationException($"应用[{app}]没有使用password密码凭证的能力!");
                }

                IManageUser user = null;
                if (password.StartsWithIgnoreCase("md5#"))
                {
                    var pass = password.Substring("md5#".Length);
                    user = User.Login(username, u =>
                    {
                        if (!u.Password.IsNullOrEmpty() && !u.Password.EqualIgnoreCase(pass))
                        {
                            throw new InvalidOperationException($"密码不正确!");
                        }
                    });
                }
                else if (password.StartsWithIgnoreCase("$rsa$"))
                {
                    var ss   = password.Split('$');
                    var key  = GetKey(ss[2]);
                    var pass = ss[ss.Length - 1];
                    pass = RSAHelper.Decrypt(pass.ToBase64(), key).ToStr();

                    if (Provider is ManageProvider prv)
                    {
                        user = prv.LoginCore(username, pass);
                    }
                    else
                    {
                        user = User.Login(username, pass, false);
                    }
                }
                else
                {
                    // 不能使用 ManagerProvider,它会写cookie
                    //var user = Provider.Login(username, password, false);
                    if (Provider is ManageProvider prv)
                    {
                        user = prv.LoginCore(username, password);
                    }
                    else
                    {
                        user = User.Login(username, password, false);
                    }
                }
                if (user == null)
                {
                    throw new XException("用户{0}验证失败", username);
                }

                var token = sso.CreateToken(app, user.Name, null, $"{client_id}#{user.Name}");

                log.AccessToken  = token.AccessToken;
                log.RefreshToken = token.RefreshToken;

                log.CreateUser = user.Name;
                log.Scope      = token.Scope;

                return(token);
            }
            catch (Exception ex)
            {
                log.Success = false;
                log.Remark  = ex.GetTrue()?.Message;

                throw;
            }
            finally
            {
                log.Insert();
            }
        }
Пример #7
0
        /// <summary>验证用户身份</summary>
        /// <remarks>
        /// 子系统需要验证访问者身份时,引导用户跳转到这里。
        /// 用户登录完成后,得到一个独一无二的code,并跳转回去子系统。
        /// </remarks>
        /// <param name="client_id">应用标识</param>
        /// <param name="redirect_uri">回调地址</param>
        /// <param name="response_type">响应类型。默认code</param>
        /// <param name="scope">授权域</param>
        /// <param name="state">用户状态数据</param>
        /// <returns></returns>
        public virtual String Authorize(String client_id, String redirect_uri, String response_type = null, String scope = null, String state = null)
        {
            var log = new AppLog
            {
                Action  = nameof(Authorize),
                Success = true,

                ClientId     = client_id,
                RedirectUri  = redirect_uri,
                ResponseType = response_type,
                Scope        = scope,
                State        = state
            };

            try
            {
                //if (client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(client_id));
                //if (redirect_uri.IsNullOrEmpty()) throw new ArgumentNullException(nameof(redirect_uri));
                //if (response_type.IsNullOrEmpty()) response_type = "code";

                if (!response_type.EqualIgnoreCase("code"))
                {
                    throw new NotSupportedException(nameof(response_type));
                }

                var app = App.FindByName(client_id);
                //if (app == null) throw new XException("未找到应用[{0}]", appid);
                // 找不到应用时自动创建,但处于禁用状态
                if (app == null)
                {
                    app = new App {
                        Name = client_id
                    };
                    app.Insert();
                }

                log.AppId = app.ID;
                if (!app.Enable)
                {
                    throw new XException("应用[{0}]不可用", client_id);
                }

                // 验证回调地址
                if (!app.ValidCallback(redirect_uri))
                {
                    throw new XException("回调地址不合法 {0}", redirect_uri);
                }

                // 统计次数
                app.Auths++;
                app.LastAuth = DateTime.Now;
                app.SaveAsync(5_000);

                if (Log != null)
                {
                    WriteLog("Authorize client_id={0} redirect_uri={1}", client_id, redirect_uri);
                }
            }
            catch (Exception ex)
            {
                log.Success = false;
                log.Remark  = ex.GetTrue()?.Message;

                throw;
            }
            finally
            {
                log.Insert();
            }

            return(log.ID + "");
        }
Пример #8
0
        /// <summary>密码式获取令牌</summary>
        /// <param name="sso"></param>
        /// <param name="client_id">应用标识</param>
        /// <param name="username">用户名</param>
        /// <param name="password">密码。支持md5密码,以md5#开头</param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public virtual TokenInfo GetAccessTokenByPassword(OAuthServer sso, String client_id, String username, String password, String ip)
        {
            var log = new AppLog
            {
                Action  = "Password",
                Success = true,

                ClientId     = client_id,
                ResponseType = "password",
                CreateIP     = ip,
            };

            try
            {
                var app = sso.Auth(client_id, null);
                log.AppId = app.ID;

                IManageUser user = null;
                if (password.StartsWithIgnoreCase("md5#"))
                {
                    var pass = password.Substring("md5#".Length);
                    user = XCode.Membership.User.Login(username, u =>
                    {
                        if (!u.Password.IsNullOrEmpty() && !u.Password.EqualIgnoreCase(pass))
                        {
                            throw new InvalidOperationException($"密码不正确!");
                        }
                    });
                }
                else
                {
                    // 不能使用 ManagerProvider,它会写cookie
                    //var user = Provider.Login(username, password, false);
                    user = XCode.Membership.User.Login(username, password, false);
                }
                if (user == null)
                {
                    throw new XException("用户{0}验证失败", username);
                }

                var token = sso.CreateToken(app, user.Name, null, $"{client_id}#{user.Name}");

                log.AccessToken  = token.AccessToken;
                log.RefreshToken = token.RefreshToken;

                log.CreateUser = user.Name;
                log.Scope      = token.Scope;

                return(token);
            }
            catch (Exception ex)
            {
                log.Success = false;
                log.Remark  = ex.GetTrue()?.Message;

                throw;
            }
            finally
            {
                log.Insert();
            }
        }