RESTful Authorization in the UI

2019-09-12 16:20发布

I have two separate applications, an API (built with Flask) and a HTML/JS UI.

The API handles both, authentication and authorisation. Authentication is already working properly using a cookie. I am having issues implementing authorisation.

In the UI, I would like to disable certain HTML input fields if the user is authenticated, but not authorised. I'd like the UI to also know if a user is not authorised so it can disable controls. The user can see the values, but not update them. Right now, my protected routes already run authorisation checks and return 401 if the user is not authorised, but I also want to make the UI aware of the authorisation level.

In applications that contain both the API and the UI, this can be done easily. For example, in Rails with CanCan, one can do: <% if can? :update, @article %>. However, since my applications are two separate applications, I am unable to do such a thing.

Since I have two separate applications, I cannot use Flasks' g session. Is returning a response header the best way to do this? Is there a convention for that? Basic authentication tokens only contain a token and not the authorisation level, thus only useful for authentication.

1条回答
冷血范
2楼-- · 2019-09-12 16:58

It all depends on what type of authorization logic you need. You're going to want some JS objects, in the example below I created an Ability object whose constructor function takes three parameters: user, car, company.

var Ability = function(user, car, company){
  this.user = user;
  this.car = car;
  this.company = company;
}

Ability.prototype.canSellCar = function(){
  return this.user.id == car.userId;
}

Ability.prototype.canWorkForCompany = function(){
   this.user.skills.forEach(function(skill, index){
     if(this.company.soughtSkills.indexOf(skill) !== undefined){
       return true
     }
   }
   return false;
}

Then you can create a new instance of the Ability object and pass it in instances of a user, car, and company, like so

var bobs_abilities = new Ability(bob, truck, government)

Finally you can call the methods you defined your ability's prototype.

if(bobs_abilities.canSellCar){
  // UPDATE THE DOM TO SHOW THE UI ELEMENT THAT CONTROLS CAR SELLING
}

Hopefully this is a good start for you. Your ability class might need to do additional steps like make api calls to your server to get more information, or you might need to pass parameters into the functions defined on the Ability prototype.

If you were doing this with angular you might make the function's on the prototype into their own directives so that your html would look like

<div can-sell-car user={{bob}} car={{truck}} company={{government}}>
  //Stuff you want to show in here
</div>

Definitely check out https://egghead.io/ if you want to look into using angular

查看更多
登录 后发表回答