Security for an AngularJs + ServiceStack App

2019-03-16 23:04发布

问题:

I have an application that have four modules in the front end, I'm trying to use as much as possible AngularJs in the front end I'm using an empty website asp.net project to host all the files and the REST serviceStack, my project have kind of the following structure:

~/ (web.config, global.asax and all the out of the box structure for an asp.net website)
- App <-  AngularJs 
    - Users  <-  js controllers and views (static html files)
    - Companies
    - BackEnd
    - Public
    Index.html
    IndexCtrl.js
    App.js
- Content
- Js

I use angularjs service calls and the backend I'm using REST with servicestack.

the question is how can I restrict the access only to authenticated users to those static html files? let's say the ones that are inside inside Companies, Backend and users for example

回答1:

Hi After doing some research this is the solution that worked for me:

  1. Install razor markdown from nuget
  2. Change the file structure to match the default behavior RM [Razor Markdown] to /views
  3. Modify the web config following the approach described in this service stack example
  4. Change all the static htmls files to .cshtml files, this by default creates the same route without the extension like /views/{Pagename} without the extension, I'm just using this approach to get the authorization logic simpler to implement (at least for me)
  5. Update the service method with an authorize attribute you can find out more in this page

to illustrate a lit of bit more this is my route definition in so far:

'use strict';
angular.module('myApp', ['myApp.directives', 'myApp.services']).config(
    ['$routeProvider', function($routeProvider) {
        $routeProvider.when('/Dashboard', {
            controller: 'dashboardCtrl',
            templateUrl: 'Views/dashboard'
            }).when('/Payments', {
            controller: 'paymentsCtrl',
            templateUrl: 'Views/payments'
        }).
            when('/Login', {
                controller: 'loginCtrl',
                templateUrl: 'Views/login'
            });
    }]

);

Notice that the references are pointed now to the razor paths.

this is a small menu I've done in angular

<div class="container">

  <div class="navbar" ng-controller="indexCtrl">
    <div class="navbar-inner">
      <a class="brand" href="#/">header menu</a>
      <ul class="nav">
         <li ng-class="{active: routeIs('/Dashboard')}"><a href="#/Dashboard">Dashboard</a></li>
         <li ng-class="{active: routeIs('/Login')}"><a href="#/Login">Login</a></li>
         <li ng-class="{active: routeIs('/Payments')}"><a href="#/Payments">payments</a></li>
      </ul>
    </div>
  </div>


  <ng-view></ng-view>

</div>

let's say that the payments page is restricted, so every time I click on a the page I get a 401 unauthorized message.

Service host:

 public override void Configure(Container container)
        { 

            Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] {
                new FacebookAuthProvider(appSettings), 
                new TwitterAuthProvider(appSettings), 
                new BasicAuthProvider(appSettings), 
                new GoogleOpenIdOAuthProvider(appSettings),
                new CredentialsAuthProvider()
            })); //I'm going to support social auth as well.

            Plugins.Add(new RegistrationFeature());

            Routes.Add<UserRequest>("/Api/User/{Id}");
            Routes.Add<LoginRequest>("/Api/User/login","POST");
            Routes.Add<PaymentRequest>("/views/Payments");


        }

I hope that helps



回答2:

Create a CatchAllHander method to check for restricted routes and, for those static files that require authentication, return the ForbiddenFileHander if not authenticated, otherwise return null. Given an isAuthenticated method and restrictedDirs is defined somewhere - maybe your app or web config file, it can be as simple as:

appHost.CatchAllHandlers.Add((httpMethod, pathInfo, filePath) => {
   if ( restrictedDirs.ContainsKey(pathInfo) && !isAuthenticated())
      return new ForbiddenHttpHandler();
   return null;
}); 


回答3:

Why not use Forms Authentication? Simply add a few < location > tags to your web.config to allow/disallow different sections, you can even do it based on roles.