ASP.NET MVC - कस्टम IIdentity या IPrincipal सेट करें


650

मुझे कुछ सरल करने की आवश्यकता है: मेरे ASP.NET MVC एप्लिकेशन में, मैं एक कस्टम IIdentity / IPrincipal सेट करना चाहता हूं। जो भी आसान / अधिक उपयुक्त है। मैं डिफ़ॉल्ट का विस्तार करने के लिए इतना है कि मैं की तरह कुछ कॉल कर सकते हैं चाहते हैं User.Identity.Idऔर User.Identity.Role। कुछ भी नहीं फैंसी, बस कुछ अतिरिक्त गुण।

मैंने बहुत सारे लेख और प्रश्न पढ़े हैं, लेकिन मुझे ऐसा महसूस हो रहा है कि मैं इसे वास्तव में जितना कठिन बना रहा हूं। मुझे लगा कि यह आसान होगा। यदि कोई उपयोगकर्ता लॉग ऑन करता है, तो मैं एक कस्टम IIdentity सेट करना चाहता हूं। इसलिए मैंने सोचा, मैं Application_PostAuthenticateRequestअपने ग्लोबल.सैक्स में लागू करूंगा। हालाँकि, यह हर अनुरोध पर कहा जाता है, और मैं हर अनुरोध पर डेटाबेस पर कॉल नहीं करना चाहता हूं जो डेटाबेस से सभी डेटा का अनुरोध करेगा और एक कस्टम IPrincipal ऑब्जेक्ट में डाल देगा। यह भी बहुत ही अनावश्यक, धीमा और गलत स्थान पर लगता है (डेटाबेस कॉल करता है) लेकिन मैं गलत हो सकता है। या फिर वह डेटा कहां से आएगा?

इसलिए मैंने सोचा, जब भी कोई उपयोगकर्ता लॉग इन करता है, मैं अपने सत्र में कुछ आवश्यक चर जोड़ सकता हूं, जिसे मैं कस्टम IIdity में जोड़ता हूं Application_PostAuthenticateRequest इवेंट हैंडलर । लेकिन, मेरा Context.Sessionहै null, वहाँ इतना है कि यह भी जाने का रास्ता नहीं है।

मैं अब एक दिन के लिए इस पर काम कर रहा हूं और मुझे लगता है कि मुझे कुछ याद आ रहा है। यह भी करना मुश्किल नहीं होना चाहिए, है ना? मैं भी सभी (अर्ध) संबंधित सामान से थोड़ा भ्रमित हूं जो इसके साथ आता है। MembershipProvider, MembershipUser, RoleProvider, ProfileProvider, IPrincipal,IIdentity , FormsAuthentication.... Am मेरे अलावा कोई और सब बहुत भ्रमित पाता है यह?

अगर कोई मुझे एक सरल, सुरुचिपूर्ण और कुशल समाधान बता सकता है, तो सभी अतिरिक्त फ़ज़ के बिना एक IIdentity पर कुछ अतिरिक्त डेटा संग्रहीत करने के लिए .. यह बहुत अच्छा होगा! मुझे पता है कि एसओ पर भी इसी तरह के सवाल हैं, लेकिन अगर मुझे जो जवाब चाहिए, वह मुझे नजरअंदाज करना होगा।


1
हाय डॉमी, यह केवल स्टोर करने वाले डेटा का एक संयोजन है जो कभी नहीं बदलता है (उपयोगकर्ता आईडी की तरह) या उपयोगकर्ता को डेटा बदलने के तुरंत बाद कुकी को अपडेट करना जो कि तुरंत कुकी में परिलक्षित होता है। यदि कोई उपयोगकर्ता ऐसा करता है, तो मैं बस नए डेटा के साथ कुकी को अपडेट करता हूं। लेकिन मैं कोशिश करता हूं कि अक्सर बदलाव करने वाले डेटा को स्टोर न करूं।
रज्जी

26
इस सवाल में 36k विचार और कई अपवोट हैं। क्या यह वास्तव में एक सामान्य आवश्यकता है - और यदि ऐसा नहीं है तो यह सब 'कस्टम सामग्री' से बेहतर तरीका नहीं है?
सिमोन_विवर

2
@Simon_Weaver ASP.NET आइडेंटिटी है, जो एन्क्रिप्टेड कुकी में अतिरिक्त कस्टम जानकारी को अधिक आसानी से समर्थन करता है।
जॉन

1
मैं आपसे सहमत हूँ, वहाँ अधिक से अधिक जानकारी के लिए है जैसे आप पोस्ट: MemberShip..., Principal, Identity। प्रमाणीकरण से निपटने के लिए ASP.NET को यह आसान, सरल और अधिकतम दो दृष्टिकोणों पर करना चाहिए।
ब्रॉडबैंड

1
@Simon_Weaver यह स्पष्ट रूप से दिखाता है कि सरल और अधिक लचीली पहचान प्रणाली IMHO की मांग है।
19

जवाबों:


838

यहाँ है कि मैं यह कैसे करते हैं।

मैंने IIdentity के बजाय IPrincipal का उपयोग करने का निर्णय लिया क्योंकि इसका मतलब है कि मुझे IIdentity और IPrincipal दोनों को लागू करने की आवश्यकता नहीं है।

  1. इंटरफ़ेस बनाएँ

    interface ICustomPrincipal : IPrincipal
    {
        int Id { get; set; }
        string FirstName { get; set; }
        string LastName { get; set; }
    }
  2. CustomPrincipal

    public class CustomPrincipal : ICustomPrincipal
    {
        public IIdentity Identity { get; private set; }
        public bool IsInRole(string role) { return false; }
    
        public CustomPrincipal(string email)
        {
            this.Identity = new GenericIdentity(email);
        }
    
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
  3. CustomPrincipalSerializeModel - FormsAuthentication.nic ऑब्जेक्ट में userdata फ़ील्ड में कस्टम जानकारी को क्रमांकित करने के लिए।

    public class CustomPrincipalSerializeModel
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
  4. लॉग इन विधि - कस्टम जानकारी के साथ एक कुकी की स्थापना

    if (Membership.ValidateUser(viewModel.Email, viewModel.Password))
    {
        var user = userRepository.Users.Where(u => u.Email == viewModel.Email).First();
    
        CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();
        serializeModel.Id = user.Id;
        serializeModel.FirstName = user.FirstName;
        serializeModel.LastName = user.LastName;
    
        JavaScriptSerializer serializer = new JavaScriptSerializer();
    
        string userData = serializer.Serialize(serializeModel);
    
        FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                 1,
                 viewModel.Email,
                 DateTime.Now,
                 DateTime.Now.AddMinutes(15),
                 false,
                 userData);
    
        string encTicket = FormsAuthentication.Encrypt(authTicket);
        HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
        Response.Cookies.Add(faCookie);
    
        return RedirectToAction("Index", "Home");
    }
  5. Global.asax.cs - कुकी पढ़ना और HttpContext.User ऑब्जेक्ट को बदलना, यह PostAuthenticateRequest को ओवरराइड करके किया जाता है

    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    
        if (authCookie != null)
        {
            FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    
            JavaScriptSerializer serializer = new JavaScriptSerializer();
    
            CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);
    
            CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
            newUser.Id = serializeModel.Id;
            newUser.FirstName = serializeModel.FirstName;
            newUser.LastName = serializeModel.LastName;
    
            HttpContext.Current.User = newUser;
        }
    }
  6. रेजर विचारों में प्रवेश

    @((User as CustomPrincipal).Id)
    @((User as CustomPrincipal).FirstName)
    @((User as CustomPrincipal).LastName)

और कोड में:

    (User as CustomPrincipal).Id
    (User as CustomPrincipal).FirstName
    (User as CustomPrincipal).LastName

मुझे लगता है कि कोड आत्म-व्याख्यात्मक है। यदि ऐसा नहीं है, तो मुझे बताएं।

इसके अतिरिक्त पहुँच को और भी आसान बनाने के लिए आप एक बेस कंट्रोलर बना सकते हैं और लौटाए गए उपयोगकर्ता ऑब्जेक्ट को ओवरराइड कर सकते हैं (HttpContext.serser):

public class BaseController : Controller
{
    protected virtual new CustomPrincipal User
    {
        get { return HttpContext.User as CustomPrincipal; }
    }
}

और फिर, प्रत्येक नियंत्रक के लिए:

public class AccountController : BaseController
{
    // ...
}

जो आपको इस तरह से कोड में कस्टम फ़ील्ड का उपयोग करने की अनुमति देगा:

User.Id
User.FirstName
User.LastName

लेकिन यह विचारों के अंदर काम नहीं करेगा। इसके लिए आपको एक कस्टम वेब व्यूपेज कार्यान्वयन बनाने की आवश्यकता होगी:

public abstract class BaseViewPage : WebViewPage
{
    public virtual new CustomPrincipal User
    {
        get { return base.User as CustomPrincipal; }
    }
}

public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
    public virtual new CustomPrincipal User
    {
        get { return base.User as CustomPrincipal; }
    }
}

इसे दृश्य / web.config में एक डिफ़ॉल्ट पृष्ठ प्रकार बनाएं:

<pages pageBaseType="Your.Namespace.BaseViewPage">
  <namespaces>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Routing" />
  </namespaces>
</pages>

और विचारों में, आप इसे इस तरह एक्सेस कर सकते हैं:

@User.FirstName
@User.LastName

9
अच्छा कार्यान्वयन; RoleManagerModule के लिए अपने कस्टम प्रिंसिपल को रोलप्रिनिपल से बदल दें। इससे मुझे बहुत दर्द हुआ - stackoverflow.com/questions/10742259/…
डेविड कीवेनी

9
ठीक है मुझे समाधान मिल गया है, बस एक और स्विच जोड़ें जो पास है "" (खाली स्ट्रिंग) ईमेल के रूप में और पहचान अनाम होगी।
पियरे-अलैन विगेंट ने

3
DateTime.Now.AddMinutes (N) ... इसे कैसे बनाया जाए ताकि यह N मिनट के बाद उपयोगकर्ता को लॉगआउट न करे, क्या उपयोगकर्ता में लॉग इन किया जा सकता है (जब उपयोगकर्ता उदाहरण के लिए 'रिमेम्बर मी' की जाँच करता है)?
1110

4
आप WebApiController का उपयोग कर रहे हैं, तो आप सेट करने की आवश्यकता होगी Thread.CurrentPrincipalपर Application_PostAuthenticateRequestइसके लिए काम करने के लिए के रूप में यह पर निर्भर नहीं करताHttpContext.Current.User
जोनाथन Levison

3
@AbhinavGujjar FormsAuthentication.SignOut();मेरे लिए ठीक काम करता है।
ल्यूकपी

109

मैं ASP.NET MVC के लिए सीधे बात नहीं कर सकता, लेकिन ASP.NET वेब प्रपत्रों के लिए, ट्रिक एक बनाने के लिए है FormsAuthenticationTicketऔर उपयोगकर्ता को प्रमाणित करने के बाद इसे कुकी में एन्क्रिप्ट करें। इस तरह, आपको केवल डेटाबेस को एक बार (या AD या जो भी आप अपना प्रमाणीकरण करने के लिए उपयोग कर रहे हैं) को कॉल करना होगा, और प्रत्येक बाद का अनुरोध कुकी में संग्रहीत टिकट के आधार पर प्रमाणित करेगा।

इस पर एक अच्छा लेख: http://www.ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html (टूटी हुई कड़ी)

संपादित करें:

चूँकि ऊपर का लिंक टूटा हुआ है, इसलिए मैं उसके उत्तर में ल्यूक के समाधान की सिफारिश करूंगा: https://stackoverflow.com/a/10524305 - मैं यह भी सुझाव दूंगा कि स्वीकृत उत्तर को उसी में बदल दिया जाए।

संपादित करें 2: टूटी हुई कड़ी का एक विकल्प: https://web.archive.org/web/20120422011422/http://ondotnet.com/pub/a/dotnet/2004/02/02/effectiveformsauth.html


PHP से आ रहा है, मैं हमेशा उपयोगकर्ता की तरह जानकारी और सत्र में प्रतिबंधित पहुँच प्रदान करने के लिए आवश्यक अन्य टुकड़े डाल दिया है। इसे क्लाइंट-साइड स्टोर करने से मुझे घबराहट होती है, क्या आप टिप्पणी कर सकते हैं कि समस्या क्यों नहीं होगी?
जॉन जुमब्रम

@ जॉन - टिकट को तार पर भेजने से पहले सर्वर पर एन्क्रिप्ट किया जाता है, इसलिए ऐसा नहीं है कि ग्राहक टिकट के भीतर संग्रहीत डेटा तक पहुंच बनाने जा रहा है। ध्यान दें कि सत्र आईडी एक कुकी में भी संग्रहीत की जाती है, इसलिए यह वास्तव में अलग नहीं है।
जॉन रास्च

3
यदि आप यहां हैं तो आपको ल्यूक के समाधान को देखना चाहिए
mynkow

2
मैं हमेशा इस दृष्टिकोण के साथ अधिकतम कुकी आकार ( stackoverflow.com/questions/8706924/… ) को पार करने की क्षमता से संबंधित रहा हूं । मैं सर्वर पर डेटा रखने के लिए Cacheएक Sessionप्रतिस्थापन के रूप में उपयोग करता हूं । क्या कोई मुझे बता सकता है कि क्या यह एक त्रुटिपूर्ण दृष्टिकोण है?
लाल ताज़

2
अच्छा तरीका। इसके साथ एक संभावित समस्या यह है कि यदि आपकी उपयोगकर्ता ऑब्जेक्ट में कुछ गुणों (और विशेष रूप से किसी भी नेस्टेड ऑब्जेक्ट) से अधिक है, तो कुकी का निर्माण चुपचाप विफल हो जाएगा, क्योंकि एन्क्रिप्टेड मूल्य 4KB के ऊपर है (हिट करने के लिए बहुत आसान है तो आप सोच सकते हैं)। यदि आप केवल कुंजी डेटा को स्टोर करते हैं तो यह ठीक है लेकिन फिर आपको बाकी के लिए DB को हिट करना होगा। एक अन्य विचार कुकी डेटा को "अपग्रेड" कर रहा है जब उपयोगकर्ता ऑब्जेक्ट में हस्ताक्षर या तर्क में परिवर्तन होता है।
ज्योफ्री हुडिक

63

यहाँ एक उदाहरण के लिए काम किया है। bool .Valid कुछ डेटा स्टोर को देखकर सेट किया गया है (आपके उपयोगकर्ता डेटा बेस को कहने देता है)। उपयोगकर्ता आईडी सिर्फ एक आईडी है जिसे मैं बनाए रख रहा हूं। आप उपयोगकर्ता डेटा के लिए ईमेल पते की तरह प्रासंगिक जानकारी जोड़ सकते हैं।

protected void btnLogin_Click(object sender, EventArgs e)
{         
    //Hard Coded for the moment
    bool isValid=true;
    if (isValid) 
    {
         string userData = String.Empty;
         userData = userData + "UserID=" + userID;
         FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, username, DateTime.Now, DateTime.Now.AddMinutes(30), true, userData);
         string encTicket = FormsAuthentication.Encrypt(ticket);
         HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
         Response.Cookies.Add(faCookie);
         //And send the user where they were heading
         string redirectUrl = FormsAuthentication.GetRedirectUrl(username, false);
         Response.Redirect(redirectUrl);
     }
}

अपनी जानकारी को पुनः प्राप्त करने के लिए निम्नलिखित कोड जोड़ें

protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[
             FormsAuthentication.FormsCookieName];
    if(authCookie != null)
    {
        //Extract the forms authentication cookie
        FormsAuthenticationTicket authTicket = 
               FormsAuthentication.Decrypt(authCookie.Value);
        // Create an Identity object
        //CustomIdentity implements System.Web.Security.IIdentity
        CustomIdentity id = GetUserIdentity(authTicket.Name);
        //CustomPrincipal implements System.Web.Security.IPrincipal
        CustomPrincipal newUser = new CustomPrincipal();
        Context.User = newUser;
    }
}

जब आप बाद में जानकारी का उपयोग करने जा रहे हैं, तो आप अपने कस्टम प्रिंसिपल को निम्नानुसार एक्सेस कर सकते हैं।

(CustomPrincipal)this.User
or 
(CustomPrincipal)this.Context.User

यह आपको कस्टम उपयोगकर्ता जानकारी तक पहुंचने की अनुमति देगा।


2
FYI करें - यह Request.Cookies है [] (बहुवचन)
Dan Esparza

10
Thread.CurrentPrincipal और Context.User को CustomPrincipal पर सेट करना न भूलें।
रस कैम

6
GetUserIdentity () कहां से आती है?
रेयान

जैसा कि मैंने टिप्पणी में उल्लेख किया है, यह System.Web.Security.IIdentity का कार्यान्वयन देता है। उस इंटरफ़ेस के बारे में Google
श्रीवंत अट्टनाके

16

MVC आपको OnAuthorize मेथड प्रदान करता है जो आपके कंट्रोलर क्लासेस से हैंग होता है। या, आप प्राधिकरण करने के लिए एक कस्टम एक्शन फ़िल्टर का उपयोग कर सकते हैं। MVC इसे करना बहुत आसान बनाता है। मैंने इस बारे में एक ब्लॉग पोस्ट यहाँ पोस्ट की। http://www.bradygaster.com/post/custom-authentication-with-mvc-3.0


लेकिन सत्र खो सकता है और उपयोगकर्ता अभी भी प्रमाणित करता है। नहीं ?
१२:११ पर ड्रैगॉफ १ou

@brady gaster, मैंने आपकी ब्लॉग पोस्ट (धन्यवाद!) पढ़ी, तो कोई व्यक्ति "OnAuthorize ()" का उपयोग कैसे करेगा। जवाब? क्या सिद्धांत उपयोगकर्ता को स्थापित करने में एक दूसरे पर पसंद किया जाता है?
RayLoveless

10

यहाँ एक समाधान है अगर आपको अपने विचारों में उपयोग के लिए कुछ विधियों को @User करने की आवश्यकता है। किसी भी गंभीर सदस्यता अनुकूलन के लिए कोई समाधान नहीं है, लेकिन अगर मूल प्रश्न अकेले विचारों के लिए आवश्यक था, तो शायद यह पर्याप्त होगा। नीचे एक ऑथराइज़फ़िल्टर से लौटाए गए चर की जाँच के लिए इस्तेमाल किया गया था, यह सत्यापित करने के लिए उपयोग किया जाता है कि कुछ लिंक प्रस्तुत किए जाने हैं या नहीं (किसी भी प्रकार के प्राधिकरण तर्क या एक्सेस अनुदान के लिए नहीं)।

using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Security.Principal;

    namespace SomeSite.Web.Helpers
    {
        public static class UserHelpers
        {
            public static bool IsEditor(this IPrincipal user)
            {
                return null; //Do some stuff
            }
        }
    }

तो बस क्षेत्रों web.config में एक संदर्भ जोड़ें, और इसे दृश्य में नीचे की तरह कॉल करें।

@User.IsEditor()

1
आपके समाधान में, हमें फिर से हर बार डेटाबेस कॉल करने की आवश्यकता है। क्योंकि उपयोगकर्ता ऑब्जेक्ट में कस्टम गुण नहीं हैं। इसमें केवल नाम और IsAuthanticated
OneNiceFriend

यह पूरी तरह से आपके कार्यान्वयन और वांछित व्यवहार पर निर्भर करता है। मेरे नमूने में डेटाबेस, या भूमिका, तर्क की 0 लाइनें शामिल हैं। यदि कोई IsInRole का उपयोग करता है, तो उसे कुकी में कैश्ड माना जा सकता है। या आप अपने स्वयं के कैशिंग तर्क को लागू करते हैं।
बेस

3

ल्यूक के जवाब के आधार पर , और सेटअप करने के लिए कुछ तरीकों को जोड़ें timeoutऔर requireSSLसहयोग करेंWeb.config

संदर्भ लिंक

ल्यूक के संशोधित कोड

1, के timeoutआधार पर सेट करें Web.ConfigFormsAuthentication.Timeout टाइमआउट मान है, जो web.config में परिभाषित किया गया है मिल जाएगा। मैंने फंक्शन होने के लिए फॉलोइंग लपेटी, जो वापस लौट ticketआए।

int version = 1;
DateTime now = DateTime.Now;

// respect to the `timeout` in Web.config.
TimeSpan timeout = FormsAuthentication.Timeout;
DateTime expire = now.Add(timeout);
bool isPersist = false;

FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
     version,          
     name,
     now,
     expire,
     isPersist,
     userData);

2, कॉन्फ़िगरेशन के आधार पर कुकी को सुरक्षित या नहीं होने के लिए RequireSSLकॉन्फ़िगर करें।

HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
// respect to `RequreSSL` in `Web.Config`
bool bSSL = FormsAuthentication.RequireSSL;
faCookie.Secure = bSSL;

3

सब ठीक है, इसलिए मैं इस बहुत पुराने प्रश्न को खींचकर यहाँ एक गंभीर क्रिप्टोकरंसी हूँ, लेकिन इसके लिए बहुत सरल दृष्टिकोण है, जो ऊपर @Baserz द्वारा छुआ गया था। और वह C # एक्सटेंशन विधियों और कैशिंग के संयोजन का उपयोग करना है (सत्र का उपयोग न करें)।

वास्तव में, Microsoft पहले से ही Microsoft.AspNet.Identity.IdentityExtensionsनामस्थान में कई ऐसे एक्सटेंशन प्रदान करता है। उदाहरण के लिए, GetUserId()एक एक्सटेंशन विधि है जो उपयोगकर्ता आईडी लौटाती है। वहाँ भी है GetUserName()और FindFirstValue()जो IPrincipal के आधार पर दावे लौटाता है।

इसलिए आपको केवल नामस्थान को शामिल करने की आवश्यकता है, और फिर User.Identity.GetUserName()ASP.NET पहचान द्वारा कॉन्फ़िगर किए गए उपयोगकर्ताओं के नाम प्राप्त करने के लिए कॉल करें ।

मुझे यकीन नहीं है कि यह कैश किया गया है, क्योंकि पुराने ASP.NET पहचान खुली नहीं है, और मैंने इसे रिवर्स करने के लिए इंजीनियर को परेशान नहीं किया है। हालांकि, अगर यह नहीं है तो आप अपनी खुद की एक्सटेंशन विधि लिख सकते हैं, जो इस परिणाम को विशिष्ट समय के लिए कैश करेगा।


क्यों "सत्र का उपयोग न करें"?
एलेक्स

@ जिटबिट - क्योंकि सत्र अविश्वसनीय है, और असुरक्षित है। उसी कारण से आपको सुरक्षा उद्देश्यों के लिए सत्र का उपयोग कभी नहीं करना चाहिए।
एरिक फनकेनबस

"अप्रतिष्ठित" को सत्र को फिर से खोलने (यदि खाली हो) द्वारा संबोधित किया जा सकता है। "असुरक्षित" - सत्र अपहरण से बचाने के तरीके हैं (HTTPS-only + अन्य तरीकों का उपयोग करके)। लेकिन मैं वास्तव में आपसे सहमत हूं। फिर आप इसे कैश कहां करेंगे? जानकारी पसंद है IsUserAdministratorया UserEmailआदि? आप सोच रहे हैं HttpRuntime.Cache?
एलेक्स

@ जिटबिट - यदि आपके पास यह एक विकल्प है, या एक और कैशिंग समाधान है। समय की अवधि के बाद कैश प्रविष्टि को समाप्त करना सुनिश्चित करें। असुरक्षित स्थानीय प्रणाली पर भी लागू होता है, क्योंकि आप मैन्युअल रूप से कुकी को बदल सकते हैं और सत्र आईडी का अनुमान लगा सकते हैं। बीच में आदमी केवल चिंता नहीं है।
एरिक फुन्केनबस

2

यदि आप अपने पृष्ठों के पीछे कोड में पहुंच को सरल बनाना चाहते हैं, तो वेब फॉर्म उपयोगकर्ताओं (MVC नहीं) के लिए ल्यूक कोड के अतिरिक्त, बस एक आधार पृष्ठ के नीचे कोड जोड़ें और अपने सभी पृष्ठों में आधार पृष्ठ प्राप्त करें:

Public Overridable Shadows ReadOnly Property User() As CustomPrincipal
    Get
        Return DirectCast(MyBase.User, CustomPrincipal)
    End Get
End Property

तो अपने कोड में आप बस का उपयोग कर सकते हैं:

User.FirstName or User.LastName

वेब प्रपत्र परिदृश्य में मुझे जो याद आ रहा है, वह है कि कोड में समान व्यवहार कैसे प्राप्त किया जाए जो पेज से बंधा न हो, उदाहरण के लिए httpmodules में मुझे हमेशा प्रत्येक वर्ग में एक कास्ट जोड़ना चाहिए या क्या इसे प्राप्त करने का कोई स्मार्ट तरीका है?

अपने जवाब के लिए धन्यवाद और LukeP को धन्यवाद के बाद से मैं अपने कस्टम उपयोगकर्ता के लिए एक आधार के रूप में अपने उदाहरण का इस्तेमाल किया (अब है जो User.Roles, User.Tasks, User.HasPath(int), User.Settings.Timeoutऔर कई अन्य अच्छा बातें)


0

मैंने ल्यूक द्वारा सुझाए गए समाधान की कोशिश की और पाया कि यह अधिकृत विशेषता का समर्थन नहीं करता है। इसलिए, मैंने इसे थोड़ा संशोधित किया।

public class UserExBusinessInfo
{
    public int BusinessID { get; set; }
    public string Name { get; set; }
}

public class UserExInfo
{
    public IEnumerable<UserExBusinessInfo> BusinessInfo { get; set; }
    public int? CurrentBusinessID { get; set; }
}

public class PrincipalEx : ClaimsPrincipal
{
    private readonly UserExInfo userExInfo;
    public UserExInfo UserExInfo => userExInfo;

    public PrincipalEx(IPrincipal baseModel, UserExInfo userExInfo)
        : base(baseModel)
    {
        this.userExInfo = userExInfo;
    }
}

public class PrincipalExSerializeModel
{
    public UserExInfo UserExInfo { get; set; }
}

public static class IPrincipalHelpers
{
    public static UserExInfo ExInfo(this IPrincipal @this) => (@this as PrincipalEx)?.UserExInfo;
}


    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Login(LoginModel details, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            AppUser user = await UserManager.FindAsync(details.Name, details.Password);

            if (user == null)
            {
                ModelState.AddModelError("", "Invalid name or password.");
            }
            else
            {
                ClaimsIdentity ident = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
                AuthManager.SignOut();
                AuthManager.SignIn(new AuthenticationProperties { IsPersistent = false }, ident);

                user.LastLoginDate = DateTime.UtcNow;
                await UserManager.UpdateAsync(user);

                PrincipalExSerializeModel serializeModel = new PrincipalExSerializeModel();
                serializeModel.UserExInfo = new UserExInfo()
                {
                    BusinessInfo = await
                        db.Businesses
                        .Where(b => user.Id.Equals(b.AspNetUserID))
                        .Select(b => new UserExBusinessInfo { BusinessID = b.BusinessID, Name = b.Name })
                        .ToListAsync()
                };

                JavaScriptSerializer serializer = new JavaScriptSerializer();

                string userData = serializer.Serialize(serializeModel);

                FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                         1,
                         details.Name,
                         DateTime.Now,
                         DateTime.Now.AddMinutes(15),
                         false,
                         userData);

                string encTicket = FormsAuthentication.Encrypt(authTicket);
                HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
                Response.Cookies.Add(faCookie);

                return RedirectToLocal(returnUrl);
            }
        }
        return View(details);
    }

और आखिरकार Global.asax.cs में

    protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
    {
        HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

        if (authCookie != null)
        {
            FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            JavaScriptSerializer serializer = new JavaScriptSerializer();
            PrincipalExSerializeModel serializeModel = serializer.Deserialize<PrincipalExSerializeModel>(authTicket.UserData);
            PrincipalEx newUser = new PrincipalEx(HttpContext.Current.User, serializeModel.UserExInfo);
            HttpContext.Current.User = newUser;
        }
    }

अब मैं केवल कॉल करके विचारों और नियंत्रकों में डेटा तक पहुंच सकता हूं

User.ExInfo()

लॉग आउट करने के लिए मैं सिर्फ कॉल करता हूं

AuthManager.SignOut();

जहाँ AuthManager है

HttpContext.GetOwinContext().Authentication
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.