asp.net एएसपी.नेट एमवीसी-कस्टम IIdentity या IPrincipal सेट करें




asp.net-mvc forms-authentication (7)

यहां एक समाधान है यदि आपको अपने विचारों में उपयोग के लिए @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()

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

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

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

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

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


नौकरी पाने के लिए यहां एक उदाहरण दिया गया है। बूल isValid कुछ डेटा स्टोर को देखकर सेट किया गया है (मान लें कि आपका उपयोगकर्ता डेटा बेस)। UserID केवल एक आईडी है जिसे मैं बनाए रख रहा हूं। आप उपयोगकर्ता डेटा पर ईमेल पते जैसी अतिरिक्त जानकारी जोड़ सकते हैं।

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

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


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

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

  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 - FormsAuthenticationTicket ऑब्जेक्ट में उपयोगकर्ता डेटा फ़ील्ड में कस्टम जानकारी को क्रमबद्ध करने के लिए।

    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.User):

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

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

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

तो आपके पीछे आपके कोड में आसानी से पहुंच सकते हैं:

User.FirstName or User.LastName

मैं वेब फॉर्म परिदृश्य में जो खो रहा हूं, वह पृष्ठ में बंधे कोड में समान व्यवहार प्राप्त करने का तरीका है, उदाहरण के लिए httpmodules में क्या मैं हमेशा प्रत्येक कक्षा में एक कलाकार जोड़ना चाहता हूं या इसे प्राप्त करने का कोई बेहतर तरीका है?

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


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


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

वास्तव में, माइक्रोसॉफ्ट ने माइक्रोसॉफ्ट में पहले से ही ऐसे कई एक्सटेंशन प्रदान किए हैं। एस्पनेट.इडेन्टिटी.इडेन्टिटी एक्सटेंशन नामस्थान। उदाहरण के लिए, GetUserId() एक एक्सटेंशन विधि है जो उपयोगकर्ता आईडी देता है। GetUserName() और GetUserName() भी है, जो GetUserName() आधार पर दावा देता है।

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

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


ल्यूकपी के उत्तर के आधार पर, और timeout सेट करने के लिए कुछ विधियां जोड़ें और आवश्यकताएं requireSSL के साथ सहयोग करें।

संदर्भ लिंक

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

1, वेब पर आधारित timeout सेट timeoutWeb.ConfigForms प्रमाणीकरण । टाइमआउट टाइमआउट मान प्राप्त करेगा, जिसे 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;






iidentity