Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Custom Attribute Error

Îåêßíçóå áðü ôï ìÝëïò anjelinio. Τελευταία δημοσίευση από το μέλος anjelinio στις 13-09-2005, 15:55. Υπάρχουν 1 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  08-09-2005, 14:23 5246

    Custom Attribute Error

    Καλησπέρα παιδιά ... έχω ένα πρόβλημα με ένα custom attribute το οποίο γράφω.

    Το project στο οποίο υπάρχει η κλάσση μου κάνει compile μια χαρά, sign κτλ κτλ κι όλα είναι καλά κι ωραία. Όταν όμως επιχειρώ να χρησιμοποιήσω το attribute σε ένα τέστ που γράφω, ο compiler μου πετάει το παρακάτω error:

    "Error Emitting attribute - 'Cannot locate Property ActionName' "

    .. παραθέτω τον κώδικα του attribute class:

    using System;

    using System.Security;

    using System.Security.Permissions;

     

    namespace SecurityContext

    {

              /// <summary>

              /// ApplicationPermissionAttribute defines a declarative attribute to be used inside code that

              /// requires ApplicationPermissions defined declaratively.

              /// </summary>

              [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]

              public class ApplicationPermissionAttribute : CodeAccessSecurityAttribute

              {

                       private string m_ActionName;

     

                       private string[] m_PrincipalNames = null;

     

                       private PrincipalType m_PrincipalType;

                       public ApplicationPermissionAttribute(SecurityAction action) : base(action) {

                                 // Do nothing here ...

                       }

     

                       /// <summary>

                       /// ActionName accessor

                       /// </summary>

                       public virtual string ActionName {

                                 get {

                                          return m_ActionName;

                                 }

     

                                 set {

                                          m_ActionName = value;

                                 }

                       }

     

                       /// <summary>

                       /// PrincipalNames accessor

                       /// </summary>

                       public virtual string[] PrincipalNames {

                                 get {

                                          return m_PrincipalNames;

                                 }

     

                                 set {

                                          m_PrincipalNames = value;

                                 }

                       }

     

                       /// <summary>

                       /// PrincipalType accesssor (User,Role)

                       /// </summary>

                       public virtual PrincipalType PrincType {

                                 get {

                                          return m_PrincipalType;

                                 }

     

                                 set {

                                          m_PrincipalType = value;

                                 }

                       }

     

                       public new bool Unrestricted {

                                 get {

                                          return false;

                                 }

     

                                 set {

                                          // Do nothing

                                 }

                       }

     

                       public override IPermission CreatePermission(){

                                 Console.Out.WriteLine("Creating a new ApplicationPermission");

                                 return new ApplicationPermission(m_ActionName, m_PrincipalNames, m_PrincipalType);

                       }

              }

    }

    .. και το χρησιμοποιώ ως εξής ...

    [ApplicationPermission(SecurityAction.Demand, ActionName="test", PrincType = PrincipalType.User, PrincipalNames = new string[]{"username"})]

    ( Είναι λίγο gay αυτό το syntax, αλλά λέει αν κάνεις subclass ενός CodeAccessSecurityAttribute τότε οφείλεις να έχεις έναν constructor που έχει μια και μοναδική παράμετρο, το SecurityAction.xxx ... gay or what ?  ... τέλος πάντων )

    Αυτά που λέτε ... καμμιά ιδέα κανείς;


    Angel
    O:]
  •  13-09-2005, 15:55 5423 σε απάντηση της 5246

    Custom Attribute sample

    ... μιας και κανείς δεν προσφέρθηκε, αναγκάστηκα να λύσω μόνος το πρόβλημά μου, ε, και σκέφτηκα να γράψω και κάτι σαν απλό παράδειγμα της διαδικασίας δημιουργίας μιας Custom Security Permission και του αντίστοιχου Attribute.

    Ας δούμε λοιπόν.

    Οι δύο βασικές κλάσσεις/interfaces στο framework που αφορούν τα παραπάνω είναι το interface IPermission και το CodeAccessSecurityAttribute. Σε περίπτωση που αναρωτιέστε, αν το custom attribute σας δεν είναι derived απ'το CodeAccessSecurityAttribute, το σύστημα, αν και θα το προσθέσει σαν declaration στο assembly της εφαρμογής σας, δεν θα το κάνει ποτέ evaluate στο runtime .. θα περνάει .. "στο ντούκου" που λέει κι ο λαός.

    Ας τα πάρουμε απ'την αρχή όμως. Πρώτα, η κλάσση AccessPermission, η custom Security Permission μου ...

    using System;

    using System.Security;

    using System.Security.Permissions;

    using System.Text;

    using System.Windows.Forms;

    using System.Threading;

     

    namespace NetStore.Security {

              [Serializable()]

              public class AccessPermission : IPermission, IUnrestrictedPermission {

                       private string _right;

     

                       public AccessPermission() {

                                 MessageBox.Show("AccessPermission.ctor 1");

                       }

     

                       public AccessPermission(PermissionState state) {

                                 MessageBox.Show("AccessPermission.ctor 2");

                                 MessageBox.Show("state=" + state.ToString());

                       }

     

                       public AccessPermission(string right) {

                                 MessageBox.Show("AccessPermission.ctor 3");

                                 _right = right;

                       }

     

                       public IPermission Copy() {

                                 MessageBox.Show("AccessPermission.Copy");

                                 return this;

                       }

     

                       public IPermission Intersect(IPermission target) {

                                 MessageBox.Show("AccessPermission.Intersect");

                                 return this;

                       }

     

                       public bool IsSubsetOf(IPermission target) {

                                 MessageBox.Show("AccessPermission.IsSubsetOf");

                                 return false;

                        }

     

                       public IPermission Union(IPermission target) {

                                 MessageBox.Show("AccessPermission.Union");

                                 return this;

                       }

     

                       public void Demand() {

                                 MessageBox.Show("AccessPermission.Demand, Right=" + _right);

                                 MessageBox.Show(((UserPrincipal)Thread.CurrentPrincipal).Identity.Name);

                                 if(!((UserPrincipal)Thread.CurrentPrincipal).HasRight(_right))

                                          throw new SecurityException("from AccessPermission.Demand()");

                                 else

                                          ((UserPrincipal)Thread.CurrentPrincipal).CurrentPermission = this;

                       }

     

                       public SecurityElement ToXml() {

                                 MessageBox.Show("AccessPermission.ToXml");

                                 SecurityElement element = new SecurityElement("Permission");

     

                                 Type type = this.GetType();

                                 StringBuilder AssemblyName = new StringBuilder(type.Assembly.ToString());

                                 AssemblyName.Replace('\"', '\'');

     

                                 element.AddAttribute("class", type.FullName + ", " + AssemblyName);

                                 element.AddAttribute("version", "1");

                                 element.AddAttribute("right", _right);

     

                                 return element;

                       }

     

                       public void FromXml(SecurityElement element) {

                                 MessageBox.Show("AccessPermission.FromXml");

                                 _right = (string)element.Attributes["right"];

                       }

     

                       public bool IsUnrestricted() {

                                 return true;

                       }

     

                       public string Right {

                                 get {

                                          return _right;

                                 }

                                 set {

                                          _right = value;

                                 }

                       }

              }

    }

    Το βασικό "catch" που πρέπει να προσέξει κάποιος εδώ, είναι να μην επιστρέφει σε καμμία περίπτωση null απο τις μεθόδους του IPermission (Union, Copy, etc.) οι οποίες έχουν IPermission return type. Κατα τη διαδικασία του compile της εφαρμογής που θα χρησιμοποιεί το Permission σας, θα εμφανιστούν τα απίστευτα copmilation error messages του στύλ "cannot emit attribute", "failed to decode embedded permission set object" και διάφορα τέτοια μηνύματα γεμάτα χρήσιμη πληροφορία ...

    Δεύτερο catch ... πρέπει να υπάρχει constructor με μοναδική παράμετρο ένα PermissionState, ακόμη κι αν δεν κάνει τίποτα.

    Περνάω στην κλάσση του custom attribute τώρα ...

    using System;

    using System.Security;

    using System.Security.Permissions;

    using System.Text;

    using System.Windows.Forms;

     

    namespace NetStore.Security

    {

              [AttributeUsageAttribute(AttributeTargets.All)]

              public class AccessPermissionAttribute: CodeAccessSecurityAttribute {

     

                       private string _right;

     

                       public AccessPermissionAttribute(SecurityAction action) : base (action) {

                       }

     

                       public override IPermission CreatePermission() {

                                 MessageBox.Show("AccessPermissionAttribute.CreatePermission()");

                                 return new AccessPermission(_right);

                       }

     

                       public string Right {

                                 set { _right = value; }

                                 get { return(_right); }

                       }

        }

    }

    Το catch εδώ είναι η παρουσία ενός και μόνο constructor, ο οποίος έχει ως παράμετρο ένα SecurityAction (.Demand, .ListDemand etc.). Οτιδήποτε άλλο θα θέλατε να έχετε ως παράμετρο στον constructor το κάνετε Property. Το framework δε θα σας αφήσει να χρησιμοποιήσετε οποιοδήποτε άλλο footprint για τον constructor ( gay or what ... ).

    Το δεύτερο catch είναι το public override IPermission CreatePermission() ...
    Μέσα εκεί κάνετε instantiate ένα AccessPermission, ανάλογα με τις τιμές των properties του custom attribute.

    Τώρα, κάνετε compile και sign το assembly (οπωσδήποτε !!!), και το προσθέτετε στο GAC.
    ( Όταν με το καλό επιχειρήσετε να χρησιμοποιήσετε το assembly σε κάποιο project, κατα το compile όσο και να έχετε το assembly  με το custom permission/attribute referenced ... το VS.NET θα κοιτάξει στο GAC να το βρεί ... bummer ... )

    Ωραία ως εδώ ... τώρα κάνετε ένα νέο project, reference το assembly με τις custom-ιες μας, και γράφετε κάτι σαν κι αυτό:

                       [AccessPermission(SecurityAction.Demand, Right="right5")]
                       public static void SecuredMethod() {

                                 MessageBox.Show("in SecuredMethod");
                       }

    ... compile (θα πεταχτούν κάτι MessageBox pop-ups αν κάνετε copy-paste τον κώδικα ως έχει, αλλά δεν ανησυχούμε .. όλα πάνε καλά ! ), run ... και θεωρητικά, ανάλογα με το τι έχετε κάνει declare στο attribute θα "περάσει" ή θα πετάξει το custom permission  ένα SecurityException ... :)

    Αυτά γι'αυτό :) .. happy custom permission coding παίδες !

    Y.Γ. ... τώρα που το ξαναδιάβασα .. μου θύμισα λίγο τη Βέφα Αλεξιάδου !!! :D



    Angel
    O:]
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems