Avatar billede websam Nybegynder
12. juli 2006 - 10:41 Der er 26 kommentarer og
2 løsninger

Membership og RoleProvider ?

Hejsa,

Jeg sidder og kigger på de nye providers i .net 2.0 MembershipProviderog RoleProvider. Der har jeg et par spørgsmål til nogle ting i forbindelse med en custom provider jeg vil lave.

1. Kan jeg uden yderligere problemer tilføje felter i min database og gemme ekstra oplysninger som navn, adresse, post nr. osv. ?

2. Set i lyset af ovenstående ville det så være bedre med en ekstra tabel i databasen til disse oplysninger frem for at gemme dem i samme tabel som login oplysninger ?

3. Forud defineret har jeg 4 roles :

Admin : denne kan foretage sig alt på admin siderne.
SemiAdmin : denne kan foretage ændringer på admin siderne for et bestemt sprog, men kan ikke slette data.
Superbruger : denne kan foretage ændringer på f.eks. et forum, men ikke slette.
Bruger : denne kan foretage ændringer for de data denne selv har tilføjet, men ikke slette.

Hvordan styrre jeg når flere roles har adgang til de samme sider men med forskellige rettigheder, nogle kan ændre og slette andre kan ikke. Kan det styrres på link nievau ?

4. Som admin på siden skal der ydermere være mulighed for at kunne oprette roles til en række forskellige forhandlere. disse vil alle sammen få adgang til en bestemt mappe, men igen skal de forskellige roles kunne se forskellige ting ud fra hvilke sider der er tildelt adgang til ved oprettelse af sider ?

Der kommer sikkert flere spørgsmål men disse var blot et par af dem jeg sidder med lige nu, håber der nogen der har den fornøden erfaring med dette og kan hjælpe mig ;o)

/websam
Avatar billede snepnet Nybegynder
12. juli 2006 - 10:51 #1
Hej Websam :o)

1.
Det er der ingen grund til - kig på Profiles.

2.
Ad 1.

3.
Forskellige muligheder her.... Dels er der kontroller hvor du vha. templates kan definere hvad der skal vises - baseret på roller.
Det kan være anvendeligt hvis du laver dine sider deklerativt.
Dels er der et api du kan bruge hvis du vil undersøge noget omkring den aktuelle bruger, hvilket jo så er praktisk hvis du bygger dine sider op dynamisk.

4.
Du kan pr. konfiguration give adgang til pr. rolle, så ingen problemer der... Der var så også lidt af svaret under 3.

Mvh
Avatar billede dr_chaos Nybegynder
12. juli 2006 - 10:53 #2
Du kan gøre det at du til en admin sætter hans roller til Admin,
SemiAdmin ,
Superbruger,Bruger

På den måde vil han automatisk få adgang til alle sider som underordnet roller har adgang til.
Avatar billede websam Nybegynder
12. juli 2006 - 11:40 #3
snepnet >>

Spm til 1.
Jeg vil kigge nærmere på det med profiles men umiddelbart skal jeg stadigt lave noget kode der opretter, redigere og sletter oplysninger i databasen ikke ?

Spm til 3.
Jeg er med på den med at nogle kontroller kan styrres på roles men forklar lige det med templates ?
Hvad mener du med at siderne laves deklerativt ?
Skal jeg forstå at jeg kan gøre noget i stil med dette :

If Roles.IsUserInRole("bruger") Then
    '--- laver noget kode der henter links fra database og viser dem
    '--- der er tildelt bruger role
ElseIf Roles.IsUserInRole("admin") Then
    '--- laver noget kode der henter links fra database og viser dem
    '--- der er tildelt admin role
End If

Spm til 4.
Men når dette skal laves fra mine adminsider og ikke direkte i web.config hvordan bære jeg mig så ad der ?

dr_chaos >> Jeg er helt med på at admin rollen skal have adgang til alt/alle sider på hele systemet. Men det er mere set i lyset af jeg laver mine sider dynamisk og ikke fysisk ;o)

/Websam
Avatar billede dr_chaos Nybegynder
12. juli 2006 - 11:49 #4
I min customroleprovider har jeg en funktion som henter roller til en bruger.
Du behøver ikke at have det custom, du skal bare sørger for at en bruger bliver tilknyttet de enkelte roller.
Så kan du bruge If Roles.IsUserInRole("bruger") Then osv.
Avatar billede snepnet Nybegynder
12. juli 2006 - 12:10 #5
1.
Nej - det behøver du ikke... Det du ønsker at have som properties på din profil, angiver du konfigurativt (i web.config).
Det dukker op i intellisence når du har gjort det.

3.
Du har f.eks. et LogInView, som giver muligheder for at rendere forskelligt afhængigt af brugerens rolle (baseret på templates) - f.eks. sådan her:

<asp:LoginView ID="LoginView1" runat="server">
<RoleGroups>
  <asp:RoleGroup Roles="Admin">
    <ContentTemplate>
      Admin startside:<br />
    </ContentTemplate>
  </asp:RoleGroup>
  <asp:RoleGroup Roles="User">
    <ContentTemplate>
      User startside:<br />
    </ContentTemplate>
  </asp:RoleGroup>
</RoleGroups>
<LoggedInTemplate>
  Velkommen min ven!
</LoggedInTemplate>
<AnonymousTemplate>
  Du er ikke logget ind... Så du får ikke noget at se!
</AnonymousTemplate>
</asp:LoginView>

Med at siderne laves deklerativt mener jeg, at du skriver det i din markup (altså i din aspx-fil) med <asp:Button ... etc.

Dit eksempel representerer så en dynamisk generering af indhold.

Mvh
Avatar billede websam Nybegynder
13. juli 2006 - 00:29 #6
Jeg vender lige tilbage når jeg har været ved at lege lidt med det hele ;o)

/Websam
Avatar billede snepnet Nybegynder
14. juli 2006 - 12:23 #7
Det gør du bare :o)
Mvh
Avatar billede websam Nybegynder
17. juli 2006 - 20:44 #8
Ok så kommer der lige et par spørgsmål ;o) Når nu jeg normalt benytter mig af at lave en info klasse til fields og properties, en business klasse til at håndtere alt imellem interface og data klasse, en data klasse der håndtere alt trafik frem og tilbage til database, kan jeg så umiddelbart lave en custom membership provider, role provider og profile provider der bygges op på samme måde ?

Det kræver selvfølgelig mere arbejde, men kan jeg have properties i en klasse, business i en anden og data i en tredje ?

Lige umiddelbart ligger måden det er lavet på i frameworket op til at man har det i en og samme klasse.

/Websam
Avatar billede snepnet Nybegynder
18. juli 2006 - 09:03 #9
Hmmm... Du tabte mig lige der websam. Er det noget konkret, eller helt generelt du spørger til nu?
Mvh
Avatar billede websam Nybegynder
23. juli 2006 - 10:03 #10
Det var for at vide om mine custom providere kunne laves opdelt i de forskellige lag jeg i forvejen bruger.

Jeg fandt følgende links på msdn de beskriver custom provider helt fint :
http://msdn2.microsoft.com/en-us/library/6tc47t75.aspx
http://msdn2.microsoft.com/en-us/library/317sza4k.aspx
http://msdn2.microsoft.com/en-us/library/ta63b872.aspx

Beklager ventetiden, men blev opereret i Fredags i min skulder så er ikke så skide frisk ;o)

/Websam
Avatar billede snepnet Nybegynder
23. juli 2006 - 16:28 #11
Det var da noget trist noget :o(
Gik det godt?
Mvh
Avatar billede websam Nybegynder
29. juli 2006 - 01:06 #12
Ok jeg har rodet lidt med en custome provider og nu har jeg lidt problemer. Min config fil ser ud som følger :

<membership defaultProvider="MyMembershipProvider">
      <providers>
        <add name="MyMembershipProvider"
            type="NewageMembershipProvider.CustomMembershipProvider"
            enablePasswordRetrieval="true"
            enablePasswordReset="true"
            requiresQuestionAndAnswer="false"
            writeExceptionsToEventLog="false"
            connectionStringName="Conn"/>
      </providers>
    </membership>

og min klasse har et namespace og klasse som følger :

namespace NewageMembershipProvider
{
    public sealed class CustomMembershipProvider : MembershipProvider
    {

    }
}

men jeg får til stadighed en fejl der siger :

    Object reference not set to an instance of an object.

i denne linie i config filen :

    type="NewageMembershipProvider.CustomMembershipProvider"

hvad gør jeg forkert ?

/Websam
Avatar billede dr_chaos Nybegynder
30. juli 2006 - 10:07 #13
Du skal override en masse metoder.
bla initialize.
Her er den sidste custommembership provider jeg brugte:
using System.Web.Security;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System;
using System.Data;
using System.Configuration;
using System.Diagnostics;
using System.Web;
using System.Globalization;
using System.Security.Cryptography;
using System.Text;
using System.Web.Configuration;


/// <summary>
/// Summary description for TIMemberShipProvider
/// </summary>
public sealed class CustomMemberShipProvider : MembershipProvider
{
    private int newPasswordLength = 2;
    private string eventSource = "CustomMemberShipProvider";
    private string eventLog = "Application";
    private string exceptionMessage = "An exception occurred. Please check the Event Log.";
    private string connectionString;

    //
    // Bruges til at bestemme enkryption værdier
    //

    private MachineKeySection machineKey;

    //
    // hvis false vises exceptionsmeddelelsen til brugeren ellers skrives den til
    //eventlog
    //

    private bool pWriteExceptionsToEventLog;

    public bool WriteExceptionsToEventLog
    {
        get { return pWriteExceptionsToEventLog; }
        set { pWriteExceptionsToEventLog = value; }
    }
    public override void Initialize(string name, NameValueCollection config)
    {
        if (config == null)
            throw new ArgumentNullException("config");
        if (name == null || name.Length == 0)
            name = "CustomMemberShipProvider";

        if (String.IsNullOrEmpty(config["description"]))
        {
            config.Remove("description");
            config.Add("description", "CustomMemberShipProvider");
        }
        // Initialize the abstract base class.
        base.Initialize(name, config);

        pApplicationName = GetConfigValue(config["applicationName"],
                                  System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
        pMaxInvalidPasswordAttempts = Convert.ToInt32(GetConfigValue(config["maxInvalidPasswordAttempts"], "5"));
        pPasswordAttemptWindow = Convert.ToInt32(GetConfigValue(config["passwordAttemptWindow"], "10"));
        pMinRequiredNonAlphanumericCharacters = Convert.ToInt32(GetConfigValue(config["minRequiredNonAlphanumericCharacters"], "1"));
        pMinRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "7"));
        pPasswordStrengthRegularExpression = Convert.ToString(GetConfigValue(config["passwordStrengthRegularExpression"], ""));
        pEnablePasswordReset = Convert.ToBoolean(GetConfigValue(config["enablePasswordReset"], "true"));
        pEnablePasswordRetrieval = Convert.ToBoolean(GetConfigValue(config["enablePasswordRetrieval"], "true"));
        pRequiresQuestionAndAnswer = Convert.ToBoolean(GetConfigValue(config["requiresQuestionAndAnswer"], "false"));
        pRequiresUniqueEmail = Convert.ToBoolean(GetConfigValue(config["requiresUniqueEmail"], "true"));
        pWriteExceptionsToEventLog = Convert.ToBoolean(GetConfigValue(config["writeExceptionsToEventLog"], "true"));


        string temp_format = config["passwordFormat"];
        if (temp_format == null)
        {
            temp_format = "Clear";
        }

        switch (temp_format)
        {
            case "Hashed":
                pPasswordFormat = MembershipPasswordFormat.Hashed;
                break;
            case "Encrypted":
                pPasswordFormat = MembershipPasswordFormat.Encrypted;
                break;
            case "Clear":
                pPasswordFormat = MembershipPasswordFormat.Clear;
                break;
            default:
                throw new ProviderException("Password format not supported.");
        }

        // Get encryption and decryption key information from the configuration.
        Configuration cfg =
          WebConfigurationManager.OpenWebConfiguration(System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath);
        machineKey = (MachineKeySection)cfg.GetSection("system.web/machineKey");
    }


    //
    // A helper function to retrieve config values from the configuration file.
    //

    private string GetConfigValue(string configValue, string defaultValue)
    {
        if (String.IsNullOrEmpty(configValue))
            return defaultValue;

        return configValue;
    }
    //
    // System.Web.Security.MembershipProvider properties.
    //


    private string pApplicationName;
    private bool pEnablePasswordReset;
    private bool pEnablePasswordRetrieval;
    private bool pRequiresQuestionAndAnswer;
    private bool pRequiresUniqueEmail;
    private int pMaxInvalidPasswordAttempts;
    private int pPasswordAttemptWindow;
    private MembershipPasswordFormat pPasswordFormat;

    public override string ApplicationName
    {
        get { return pApplicationName; }
        set { pApplicationName = value; }
    }

    public override bool EnablePasswordReset
    {
        get { return pEnablePasswordReset; }
    }


    public override bool EnablePasswordRetrieval
    {
        get { return pEnablePasswordRetrieval; }
    }


    public override bool RequiresQuestionAndAnswer
    {
        get { return pRequiresQuestionAndAnswer; }
    }


    public override bool RequiresUniqueEmail
    {
        get { return pRequiresUniqueEmail; }
    }


    public override int MaxInvalidPasswordAttempts
    {
        get { return pMaxInvalidPasswordAttempts; }
    }


    public override int PasswordAttemptWindow
    {
        get { return pPasswordAttemptWindow; }
    }


    public override MembershipPasswordFormat PasswordFormat
    {
        get { return pPasswordFormat; }
    }

    private int pMinRequiredNonAlphanumericCharacters;

    public override int MinRequiredNonAlphanumericCharacters
    {
        get { return pMinRequiredNonAlphanumericCharacters; }
    }

    private int pMinRequiredPasswordLength;

    public override int MinRequiredPasswordLength
    {
        get { return pMinRequiredPasswordLength; }
    }

    private string pPasswordStrengthRegularExpression;

    public override string PasswordStrengthRegularExpression
    {
        get { return pPasswordStrengthRegularExpression; }
    }

    //
    // System.Web.Security.MembershipProvider methods.
    //

    //
    // MembershipProvider.ChangePassword
    //

    public override bool ChangePassword(string username, string oldPwd, string newPwd)
    {
        ValidatePasswordEventArgs args =
        new ValidatePasswordEventArgs(username, newPwd, true);

        OnValidatingPassword(args);

        if (args.Cancel)
            if (args.FailureInformation != null)
                throw args.FailureInformation;
            else
                throw new MembershipPasswordException("Change password canceled due to new password validation failure.");


        /* if (Bruger.SkiftPassword(username, newPwd))
            return true;
        else*/
        return false;
    }

    public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    public override bool DeleteUser(string username, bool deleteAllRelatedData)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    //
    // MembershipProvider.GetAllUsers
    //

    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    //
    // MembershipProvider.GetNumberOfUsersOnline
    //

    public override int GetNumberOfUsersOnline()
    {
        throw new Exception("The method or operation is not implemented.");
    }
    //
    // MembershipProvider.GetUser(string, bool)
    //

    public override MembershipUser GetUser(string username, bool userIsOnline)
    {
        using (DataSet ds = Bruger.GetBruger().FindBrugerInfoMedBrugerNavn(username))
        {
            try
            {
                DataRow dr = ds.Tables[0].Rows[0];
                MembershipUser u = new MembershipUser(this.Name, username, dr["BrugerID"], dr["Email"].ToString(), "", "", true, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
                return u;
            }
            catch (Exception e)
            {
                WriteToEventLog(e, "GetUser");
                return null;
            }
        }



    }
    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    //
    // MembershipProvider.UnlockUser
    //

    public override bool UnlockUser(string username)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    //
    // MembershipProvider.GetUserNameByEmail
    //

    public override string GetUserNameByEmail(string email)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    //
    // MembershipProvider.ResetPassword
    //

    public override string ResetPassword(string username, string answer)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    //
    // MembershipProvider.UpdateUser
    //

    public override void UpdateUser(MembershipUser user)
    {
        throw new Exception("The method or operation is not implemented.");
    }



    public override bool ValidateUser(string username, string password)
    {
        Bruger b = Bruger.GetBruger();
       
        username = HttpUtility.HtmlEncode(username);
        password = HttpUtility.HtmlEncode(password);
        if (b.Valider(username, password))
        {
            return true;
        }
        else
            return false;
    }
    //
    // MembershipProvider.FindUsersByName
    //

    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    public override string GetPassword(string username, string answer)
    {
        throw new Exception("The method or operation is not implemented.");
    }
    //
    // WriteToEventLog
    //  A helper function that writes exception detail to the event log. Exceptions
    // are written to the event log as a security measure to avoid private database
    // details from being returned to the browser. If a method does not return a status
    // or boolean indicating the action succeeded or failed, a generic exception is also
    // thrown by the caller.
    //

    private void WriteToEventLog(Exception e, string action)
    {
        EventLog log = new EventLog();
        log.Source = eventSource;
        log.Log = eventLog;

        string message = "An exception occurred communicating with the data source.\n\n";
        message += "Action: " + action + "\n\n";
        message += "Exception: " + e.ToString();

        log.WriteEntry(message);
    }

}
Avatar billede dr_chaos Nybegynder
30. juli 2006 - 10:08 #14
I min web.config har jeg:
<membership defaultProvider="CustomMemberShipProvider" userIsOnlineTimeWindow="15">
            <providers>
                <add name="CustomMemberShipProvider" type="CustomMemberShipProvider" connectionStringName="ConnectionString" enablePasswordRetrieval="true" enablePasswordReset="false" requiresQuestionAndAnswer="false" writeExceptionsToEventLog="true"/>
            </providers>
        </membership>
Avatar billede websam Nybegynder
30. juli 2006 - 13:18 #15
Fejlen jeg fik forleden er rettet, det var fordi jeg havde glemt at sætte connectionstringname til det samme som i min connectionstring.

Derudover er der så kommet lidt andet til. I initialize metoden laver jeg følgende :

_MinRequiredPasswordLength = Convert.ToInt32(GetConfigValue(config["minRequiredPasswordLength"], "6"));

Dertil har jeg så :

private int _MinRequiredPasswordLength;

public override int MinRequiredPasswordLength
    {
        get { return _MinRequiredPasswordLength; }
    }

Og i min web.config laver jeg :

minRequiredPasswordLength="8"

Men uanset hvad jeg skriver her kan jeg oprette en bruger med x antal karaktere i password uden der angives fejl ?

/Websam
Avatar billede dr_chaos Nybegynder
30. juli 2006 - 13:31 #16
OK men jeg tror godt at man kan oprette brugeren men at du måske får fejl ved login.

se evt her:
www.15seconds.com/Issue/050216.htm+asp.net+custom+membershipprovider+password&hl=da&gl=dk&ct=clnk&cd=5&client=firefox-a" target="_blank">http://64.233.183.104/search?q=cache:qaQF5OhkSRcJ:www.15seconds.com/Issue/050216.htm+asp.net+custom+membershipprovider+password&hl=da&gl=dk&ct=clnk&cd=5&client=firefox-a
Avatar billede websam Nybegynder
30. juli 2006 - 13:41 #17
Jeg glemte at skrive at dette ikke kun er den eneste der er andre som at hente password og reset password ect. der heller ikke bliver aktiveret.

Hvad kan dette skyldes ?

/Websam
Avatar billede dr_chaos Nybegynder
30. juli 2006 - 13:48 #18
hvordan ser din web.config ud ?
og hele din customprovider ?
Avatar billede websam Nybegynder
30. juli 2006 - 13:50 #19
For øvrigt kan jeg godt oprette brugeren og logge ind efterfølgende. Problemet ligger i at jeg vil angive et minimum karaktere på 8 som tilsyneladende ikke hentes i min config fil.

/Websam
Avatar billede websam Nybegynder
30. juli 2006 - 13:51 #20
min config fil er denne :

<membership defaultProvider="CustomMembershipProvider">
      <providers>
        <add name="CustomMembershipProvider"
            type="NewageMembershipProvider.CustomMembershipProvider"
            enablePasswordRetrieval="true"
            enablePasswordReset="true"
            requiresQuestionAndAnswer="false"
            writeExceptionsToEventLog="false"
            passwordFormat="Encrypted"
            connectionStringName="ConnectionString"/>
      </providers>
    </membership>

Selve klassen er på 1400+ linier så den er nok lige  lang nok at poset her !?!

/Websam
Avatar billede dr_chaos Nybegynder
30. juli 2006 - 14:33 #21
prøv med


<membership defaultProvider="CustomMembershipProvider">
      <providers>
        <add name="CustomMembershipProvider"
            type="NewageMembershipProvider.CustomMembershipProvider"
            enablePasswordRetrieval="true"
            enablePasswordReset="true"
            requiresQuestionAndAnswer="false"
            writeExceptionsToEventLog="false"
            passwordFormat="Encrypted"
            connectionStringName="ConnectionString"
minRequiredPasswordLength="8"
/>
      </providers>
    </membership>
Avatar billede websam Nybegynder
30. juli 2006 - 14:46 #22
Det ar jeg forsøgt men jeg kan stadigt oprette en bruger med et password på 4 karaktere "test" og det skulle jo ikke være muligt ?

/Websam
Avatar billede snepnet Nybegynder
30. juli 2006 - 21:30 #23
Hvis du selv har skrevet provideren (og baseret den på den generelle MemberShipProvider) - er det jo også dig selv der skriver koden til at sikre at adgangskoden overholdet det du har angivet i konfigurationsfilen.
Har du noget kode vi kan kigge på hvor du forholder til parameteren?
Mvh
Avatar billede snepnet Nybegynder
30. juli 2006 - 21:36 #24
I dit override af CreateUser må du selv kontrollere om adgangskoden har tilstrækkelig længde.
Mvh
Avatar billede websam Nybegynder
30. juli 2006 - 22:03 #25
Ja jeg kan godt se at jeg lige mangler at tjekke op på noget af det i min kode jeg kigger lige på det og ser om ikke det bare er det der skal til.

/Websam
Avatar billede websam Nybegynder
09. august 2006 - 12:06 #26
Skal vi ikke få lukket denne tråd ?
Avatar billede snepnet Nybegynder
09. august 2006 - 12:46 #27
Det kan vi godt ... skal vi smide nogle svar?
Mvh
Avatar billede dr_chaos Nybegynder
09. august 2006 - 16:45 #28
stiller samme spm som snepnet :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester