/// <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 + ""); }
/// <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(); } }
/// <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(); } }
/// <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(); } }
/// <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(); } }
/// <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(); } }
/// <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 + ""); }
/// <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(); } }