Set Xamarin WebView Cookie to seamlessly authenticate user without re-entering credentials

半腔热情 提交于 2020-06-29 06:05:42

问题


I have a Xamarin forms mobile app where the user authenticates using a post REST API and I am going to save the returned ASP.NET session ID and the authentication cookie to later pass it to my WebView in the main page to load a web page that needs authentication. For this, I created a custom web view renderer and followed some guides that suggested how to pass the cookie in the cookie container to the WebView for each request. But that does not work and I get to the login page of our website. Please advise.

WebView Renderer (IOS):

[assembly: ExportRenderer(typeof(CookieWebView), typeof(CookieWebViewRenderer))]
namespace perfectmobile.iOS
{
    public class CookieWebViewRenderer: WebViewRenderer
    {
        public CookieWebView CookieWebView
        {
            get { return Element as CookieWebView; }
        }

        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if (e.NewElement != null)
            {
                Delegate = (UIKit.IUIWebViewDelegate)new WebViewDelegate(CookieWebView);
            }

        }
    }

    internal class WebViewDelegate : UIWebViewDelegate
    {
        private CookieWebView _cookieWebView;

        public WebViewDelegate(CookieWebView cookieWebView)
        {
            _cookieWebView = cookieWebView;
        }



        public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType)
        {
            // Set cookies here
            var cookieJar = NSHttpCookieStorage.SharedStorage;
            cookieJar.AcceptPolicy = NSHttpCookieAcceptPolicy.Always;

            //clean up old cookies
            foreach (var aCookie in cookieJar.Cookies)
            {
                cookieJar.DeleteCookie(aCookie);
            }
            //set up the new cookies
            var jCookies = _cookieWebView.Cookies.GetCookies(request.Url);
            IList<NSHttpCookie> eCookies =
                (from object jCookie in jCookies
                 where jCookie != null
                 select (Cookie)jCookie
                 into netCookie
                 select new NSHttpCookie(netCookie)).ToList();

            foreach (var ck in eCookies)
            {
                cookieJar.SetCookie(ck);
            }


            return true;
        }

        public override void LoadFailed(UIWebView webView, NSError error)
        {
            // TODO: Display Error Here
            Debug.WriteLine("ERROR: {0}", error.ToString());
        }


        public override void LoadingFinished(UIWebView webView)
        {


        }

    }
}

//===================PCL project  Cookie webview ========//


public class CookieWebView : WebView
    {

        public static readonly BindableProperty CookiesProperty = BindableProperty.Create(
    propertyName: "Cookies",
        returnType: typeof(CookieContainer),
        declaringType: typeof(CookieWebView),
      defaultValue: default(string));

        public CookieContainer Cookies
        {
            get { return (CookieContainer)GetValue(CookiesProperty); }
            set { SetValue(CookiesProperty, value); }
        }

        public CookieWebView()
        {
            Cookies = new CookieContainer();
        }

    }
//========= Login ======//
var handler = new HttpClientHandler();
            handler.CookieContainer = UserInfo.CookieContainer;

            HttpClient client = new HttpClient(handler);
            HttpContent content = new StringContent("");
            content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");

            Uri uri = new Uri(LoginUrl);
            var response = client.PostAsync(uri,content);
            var responseResult = response.Result;
            if (responseResult.IsSuccessStatusCode)
            {               
                IEnumerable<Cookie> responseCookies = UserInfo.CookieContainer.GetCookies(uri).Cast<Cookie>();
                foreach (Cookie cookie in responseCookies)
                {
                    UserInfo.CookieContainer.Add(uri, cookie);                 
                }              
            }
//======== User Info =======//
public class UserInfo
    {
        public static CookieContainer CookieContainer = new CookieContainer();
    }
// ======== Main Page Xaml =======//
 <local:CookieWebView x:Name="webView" Source="Url of the website page " WidthRequest="1000" HeightRequest="1000" />
//========= Main page.cs ==========//
public partial class MainTabbedPage : ContentPage
    {
        public MainTabbedPage()
        {
            InitializeComponent();         
            webView.Cookies = UserInfo.CookieContainer;           
        }

回答1:


You need to create a custom control in your PCL-Project and then add a custom webview for each platform. The platform secific implementation then gets the coockies and you can use it from your pcl-webview.

Android

var cookieHeader = CookieManager.Instance.GetCookie(url);

iOS

NSHttpCookieStorage storage = NSHttpCookieStorage.SharedStorage;

And you can check https://github.com/seansparkman/CookiesWebView for more details .



来源:https://stackoverflow.com/questions/57051774/set-xamarin-webview-cookie-to-seamlessly-authenticate-user-without-re-entering-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!