Freigeben über


Authorization Sample 201

The attached properties described in Authorization 101 will get you going. It may even be a long time before you need more. If you find yourself chafing at the limits, though, then this section is for you. It works through some of first customization steps most applications will find useful.

Custom Authorization

Authorization is implemented using AuthorizationAttributes. If you’ve used ValidationAttributes in Silverlight, this approach should feel familiar to you. Custom authorization can be added by simply extending the AuthorizationAttribute and implementing the IsAuthorized method. These attributes can then be applied to a navigation Page or any other type where authorization would be useful.

In addition to attribute-based authorization, rule-based authorization is also available for convenient use in xaml. To implement rule-based authorization, you will need to create a new class that derives from AuthorizationRule and override the GetAuthorizationAttributes method.

   public class CustomAuthorizationRule : AuthorizationRule
  {
      public override IEnumerable<AuthorizationAttribute>
                        GetAuthorizationAttributes(object target)
      {
          return new[] { new CustomAuthorizationAttribute() };
      }
  }

You can now reference this authorization method from anywhere in xaml using the Rule property. The following snippet displays the hyperlink according to your custom authorization rule.

   <HyperlinkButton NavigateUri="/Accounts">
      <s:Authorization.Rule>
          <my:CustomAuthorizationRule />
      </s:Authorization.Rule>
  </HyperlinkButton>

Custom Behaviors

You may have noticed not all elements are hidden when the RequiresAuthentication and RequiresRole properties are applied. Pages, for instance, are simply disabled. Even though the default behavior is determined based on element type, each element can specifically declare how authorization should be applied using the TargetProperties property. The following snippet disables the hyperlink for users who are not in the ‘Administrator’ role.

   <HyperlinkButton NavigateUri="/Accounts"
                   s:Authorization.RequiresRole="Administrator"
                   s:Authorization.TargetProperties="IsEnabled" />

The TargetProperties property can be set on an element to any DependencyProperty that is a type supported by the AuthorizationConverter. Most notably, these types include Strings, Booleans, and Visibility. Also, like RequiresRole, the TargetProperties property supports a comma-separated list of property names.

Sometimes simply redirecting the user when they try to access a page they are not allowed to view is not the best option. Often, it is useful to prompt the user for their login credentials. If you set the NavigationMode to Prompt, the framework will attempt to do just that.

Using Prompt mode requires you to implement an AuthorizationPrompter, a simple interface used to prompt the user for credentials. A single instance can be created at startup and will be used throughout.

   public App()
  {
      // ...
      Authorization.Prompter = new LoginRegistrationWindowPrompter();
  }

Additionally, a Page and Frame can specify different NavigationModes. The value specified by the Frame will be used as the default. If a Page chooses to specify a value as well, it will be used instead of the default.

Comments

  • Anonymous
    October 15, 2010
    what's  LoginRegistrationWindowPrompter? how to define?could you give me a link to sourcecode? 568264099@qq.com or facingwaller@gmail.com

  • Anonymous
    October 19, 2010
    The source code for this sample is available here. blogs.msdn.com/.../silverlight-authorization-sample.aspx

  • Anonymous
    January 19, 2011
    Great stuff Kyle.  Is there any tricks to getting the NavigationMode="Prompt" to work in the AuthorizationSample project?   I've tried a few combinations with Requires Role & Authentication and TargetProperties, but I think this basic scenario should prompt with a Login dialog if the user isn't authenticated? <HyperlinkButton x:Name="LinkAbout" Style="{StaticResource LinkStyle}"                                         s:Authorization.NavigationMode="Prompt"                                     NavigateUri="/About" TargetName="ContentFrame" Content="About Us"/>

  • Anonymous
    January 19, 2011
    Also... After digging around looking for straightforward methodology for page level security, it seems this approach should be included in the next Silverlight release directly...

  • Anonymous
    January 19, 2011
    @Matt Thanks. NavigationMode is only designed to be set at a Frame level (and optionally overridden at the Page level). Using it with any other controls won't work. So there are really three steps to take for each page.

  1. Make sure the containing Frame has a NavigationMode specified
  2. Add authorization to the Page
  3. Add authorization to Hyperlinks that navigate to the page
  • Anonymous
    January 20, 2011
    The comment has been removed

  • Anonymous
    April 08, 2011
    Kyle this is once again amazing stuff. Just interestingly, I do get a warning: base type 'FirstLook.ServiceModel.DomainServices.Client.Security.AuthorizationPrompter' is not CLS-compliant Code does compile and work flawlessly.

  • Anonymous
    May 16, 2011
    I get the same CLS-compliant warnings.  What's up with that?

  • Anonymous
    August 21, 2011
    HI, It is easy to confuse the mechanism of authentication with that of authorization. In many host-based systems (and even some client/server systems), the two mechanisms are performed by the same physical hardware and, in some cases, the same software.nice one

  • Anonymous
    October 02, 2011
    The comment has been removed

  • Anonymous
    October 03, 2011
    The redirect is baked in to the library. It should be sending you back to the page you default your frame to. Here's the VB equivalent of the code above and it's important to include it in the prompter.  window.Closed += Function(sender, e) completionCallback(userState)

  • Anonymous
    October 17, 2011
    Hi, In my application when app loads,login is prompted. ie,on http://localhost:2555/AuthorizationSampleTestPage.aspx#/Home page, login child window pops.After sucessful login i click a link to redirect to 'about' page. ie,http://localhost:2555/AuthorizationSampleTestPage.aspx#/About. It works fine. But when the copy the above link and paste it to another tab, About page comes with login prompt. I mean login is prompted although the app get redirect to about us page. I can see the about page in background. So my question is how can i remain in Home page when i copy the 'about' page link in browser if i am not authenticated?Or when I paste a link to another page I should get redirect to first page,if i am not authenticated.

  • Anonymous
    October 17, 2011
    @ajin If you want the default behavior to redirection, but you want prompting on the home page (or vice versa), then you should be able to set the default NavigationMode on the Frame and set exceptional NavigationModes on specific pages. The authorization logic is based on the current value in WebContext.Current.User. When you navigate in using a deep link, you need to make sure that value is up-to-date. Typically you'd call WebContext.Current.Authentication.LoadUser() and wait for it to return before loading the page with the navigation frame (for instance, you could make the call in App.xaml.cs before making MainPage the RootVisual.

  • Anonymous
    October 23, 2011
    ''s:Authorization.TargetProperties''. i cannot access the Targetproperties . cannot resolve targetproperties error.

  • Anonymous
    October 24, 2011
    Have you added the following to the xmlns includes? xmlns:s="clr-namespace:FirstLook.ServiceModel.DomainServices.Client.Security; assembly=FirstLook.ServiceModel.DomainServices.Client.Security"

  • Anonymous
    October 24, 2011
    The comment has been removed

  • Anonymous
    October 25, 2011
    @Olly In the prompter, it's important to invoke the callback. If the prompter opens a window, then it's easiest to invoke the callback in the Closed event. How exactly you choose to do this is up to you. In my response to ajin on the 18th, I explain why this happens. Typically you'll want to fix it by loading the user in App.xaml.cs.