using System; using System.Collections.Generic; using System.Text; using System.Linq; using UMC.Data; using UMC.Net; using UMC.Web; using UMC.Security; using UMC.Proxy.Entities; using System.Collections; namespace UMC.Proxy { [Mapping(Weight = 0, Desc = "云模块服务组件")] public class WebFactory : IWebFactory { internal static Dictionary> Auths = new Dictionary>(); class XHRActivity : WebActivity { public XHRActivity(SiteConfig site) { this.site = site; } SiteConfig site; public override void ProcessActivity(WebRequest request, WebResponse response) { var user = this.Context.Token.Identity(); var httpProxy = new HttpProxy(site, this.Context.Client.Context, -1, "/", String.Empty); if (httpProxy.Domain == null) { this.Prompt("安全审记", $"此应用临时关闭,请联系应用管理员"); } switch (site.Site.UserModel) { case UserModel.Bridge: break; default: this.Prompt("UMC云模块只支持权限桥接模式"); break; } if (Auths.TryGetValue(site.Root, out var _dic) == false) { _dic = new Dictionary(); new Uri(httpProxy.Domain, "/UMC/System/Setup/Mapping").WebRequest().Get(r => { r.ReadAsString(js => { var ds = JSON.Deserialize(js) as Hashtable; if (ds?.ContainsKey("data") == true) { var data = ds["data"] as Array; foreach (var o in data) { var dic = o as Hashtable; if (dic.ContainsKey("model")) { var model = dic["model"] as string; var auth = dic["auth"] as string; WebAuthType authType = WebAuthType.All; switch (auth) { case "all": continue; case "admin": authType = WebAuthType.Admin; break; case "guest": authType = WebAuthType.Guest; break; case "user": authType = WebAuthType.User; break; case "usercheck": authType = WebAuthType.UserCheck; break; case "check": authType = WebAuthType.Check; break; } if (dic.ContainsKey("cmd")) { _dic[$"{model}.{dic["cmd"]}"] = authType; } else { _dic[model] = authType; } } } Auths[site.Root] = _dic; } }, e => { }); }); } if (this.Context.Items.Contains(typeof(WebFactory)) == false) { if (site.Site.IsAuth == true) { if (WebClient.Verify(httpProxy.Account, site.Site.SiteKey.Value, request.Model, request.Command, _dic) == false) { if (!user.IsAuthenticated) this.Context.Send("Login", false); this.Prompt("访问此云模块受限"); } } else { if (WebClient.Verify(user, 0, request.Model, request.Command, _dic) == false) { if (!user.IsAuthenticated) this.Context.Send("Login", false); this.Prompt("访问此云模块受限"); } } this.Context.Items[typeof(WebFactory)] = true; } StringBuilder sb = new StringBuilder(); sb.Append("_model="); sb.Append(request.Model); sb.Append("&_cmd="); sb.Append(request.Command); var sv = request.SendValues; if (sv != null) { var em = sv.GetDictionary().GetEnumerator(); while (em.MoveNext()) { sb.Append("&"); sb.Append(Uri.EscapeDataString(em.Key.ToString())); sb.Append("="); sb.Append(Uri.EscapeDataString(em.Value.ToString())); } } var values = request.Headers.GetDictionary()[request.Command]; if (values is string) { sb.Append("&_="); sb.Append(Uri.EscapeDataString(values as string)); } else if (values is string[]) { var stv = values as string[]; if (stv.Length > 0) { sb.Append("&__="); sb.Append(Uri.EscapeDataString(String.Join('/', stv))); } } httpProxy.AuthBridge(); var query = request.Url.Query ?? ""; if (query.StartsWith("?_v=")) { int v = query.IndexOf('&'); if (v > 0) { query = query.Substring(0, v); } } var content = this.Context.Client.Context; var webReq = httpProxy.Reqesut(content.Transfer(httpProxy.Domain)); webReq.RawUrl = $"/UMC/{Utility.Guid(this.Context.Token.Device.Value)}/{query}"; webReq.ContentType = "application/x-www-form-urlencoded"; webReq.Post(sb.ToString(), res => { int StatusCode = (int)res.StatusCode; if (StatusCode > 300 && StatusCode < 400) { httpProxy.ProcessEnd(); var url = res.Headers.Get("Location"); response.Redirect(new Uri(content.Url, url)); this.Context.OutputFinish(); } else { res.ReadAsString(xhr => { httpProxy.ProcessEnd(); String eventPfx = "{\"ClientEvent\":"; if (xhr.StartsWith(eventPfx)) { var xData = JSON.Deserialize(xhr) as Hashtable; var webEvent = (WebEvent)Utility.Parse(xData["ClientEvent"].ToString(), 0); response.ClientEvent = webEvent; if (xData.ContainsKey("Headers")) { var header = xData["Headers"] as Hashtable; var m = header.GetEnumerator(); while (m.MoveNext()) { response.Headers.Put(m.Key as string, m.Value); } } if (xData.ContainsKey("Redirect")) { var redirect = xData["Redirect"] as Hashtable; var model = redirect["model"] as string; var cmd = redirect["cmd"] as string; if (String.IsNullOrEmpty(model) == false && String.IsNullOrEmpty(cmd) == false) { var send = redirect["send"]; if (send is IDictionary) { response.Redirect(model, cmd, new WebMeta(send as IDictionary), false); } else if (send is string) { response.Redirect(model, cmd, send as string, false); } else { response.Redirect(model, cmd, false); } } } } else { response.Headers.Put("Data", Data.JSON.Expression(xhr)); response.ClientEvent |= (WebEvent)131072; } this.Context.OutputFinish(); }, error => { if (error is WebAbortException) { this.Context.OutputFinish(); } else { this.Context.Client.Context.Error(error); } }); } }); response.Redirect(Empty); } } class XHRFlow : WebFlow { public override WebActivity GetFirstActivity() { var m = this.Context.Request.Model; var cmd = this.Context.Request.Command; var cgf = Data.Reflection.Configuration("UMC"); var p = cgf[$"{m}.{cmd}"] ?? cgf[$"{m}.*"]; if (p != null) { var root = p.Attributes["root"]; if (String.IsNullOrEmpty(root) == false) { var site = DataFactory.Instance().SiteConfig(p.Attributes["root"]); if (site != null) return new XHRActivity(site); } } return WebActivity.Empty; } } public virtual WebFlow GetFlowHandler(string mode) { return new XHRFlow(); } /// /// 请在此方法中完成url与model的注册,即调用registerModel方法 /// /// public virtual void OnInit(WebContext context) { } } }