Restricting Data Returned from a Grails Restful Se

2019-04-15 02:47发布

问题:

I am new to using AngularJS and wanted to integrate with Grails using REST. While I have found many great tutorials on using Grails/AngularJS to perform CRUD operations, I have found little to help me understand the best way to restrict data returned to Angular from a Grails RESTful service based on the user logged in. I hate to ask an opinion question here as I know it is a bit frowned upon but in this case I think it is relevant and could really be beneficial for others learning how to build real world applications with Grails/Angular.

So lets say we have a simple Domain Class:

    class Book {

    String title
    String author

    static constraints = {
    }
}

and we expose this as a RESTful controller (plain vanilla)

    import grails.rest.RestfulController

class BookController extends RestfulController<Book>{

    def springSecurityService
    static responseFormats = ['json', 'xml']

    BookController(){
        super(Book)
    }

}

In my case I am using the asset-pipeline Grails plugin. I have an angular controller:

var book = angular.module('book', []);

book.controller('BookCtrl',
    function ($scope, $http) {

        $scope.getBook = function () {
            $http.get('/myApp/book').
                success(function (data) {
                    console.log("success: " + data);
                    $scope.book = data;
                }).error(function (data) {
                    console.log("error: " + data);
                    $scope.book = data;
                });
        };

        $scope.getBook();
    }
);

and view (abbreviated):

    <div>
        <table class="table table-hover">
            <tr>
                <th>Title</th>
                <th>Author</th>
            </tr>

            <tr ng-repeat="b in book">
                <td>{{b.title}}</td>
                <td>{{b.author}}</td>
            </tr>
        </table>
    </div>

When I am simply looking for the list of all Book Objects this works just fine, I get a nice table of books. But when I would like say limit the books returned based on the user logged in (let's say in this case it is a list of Books the user owns), I am not sure what may be the best way to proceed. From an authentication standpoint I thought that perhaps using the Spring Security REST plugin might be helpful in passing a token as a parameter to the BookController (assuming I override the index() method). I could then look up the token and filter results in the REST response. Does this seem like the proper approach? Thank you for any feedback,

回答1:

Yes, refer this sample Angular/Grails app which uses grails-spring-security-rest plugin for token based authn/authz. To answer your question, you have to do both:

  1. Token based authentication from client (Angular) to access the REST service.
  2. Filtering user owning books in the server side.

Token based authentication is showcased in the sample app. For filtering user, you might end up doing this in your controller:

def index() {

    //getPrincipal() is a method on controller metaClass
    //used here for convenience which is similar to saying
    //springSecurityService.principal.username

    respond Book.findByUser( principal.username )
}

Above would work based on the assumption you mentioned that there would be a join table somewhere to say a logged in user owns books.