Using Spring Security we use hasAuthority to conditionally execute code or conditionally display parts of page in jsp.
eg:
#PreAuthorize("hasAuthority('ROLE_TELLER')")
public Account post(Account account, double amount);
}
or (in jsp)
<sec:authorize access="hasAuthority('TAG_SAVE')">
.... content to display / evaluate
</sec:authorize>
I wanted to know how to handle a case when you want to show / execute something when not having Authority.
may something like
doesNotHaveAuthority('TAG_SAVE')
I am pretty sure, this is not an out of the blue use-case.
Has anyone handle this in any way?
Actually found that this can use EL.
So Using a ! sign works.
So I got it work like this:
<sec:authorize access="!hasAuthority('TAG_SAVE')">
.... content to display / evaluate when the Authority is not present
</sec:authorize>
Related
Grails 2.4.5 here. I am trying to implement the following UX behavior for my GSPs:
If a user has permission to click a button, then they may do so; however
If the user doesn't have permission to click a button, then when they click the button, a banner message (flash?) appears across the top of the screen with an rose/pinkish/red background stating 'You don't have permission to take this action'
To determine whether the user has the required permission, I have access to functionality from both the Groovy and GSP/taglib layers.
From the Groovy/controller layer:
SecurityUtils.hasPermission(String permission)
Ex: SecurityUtils.hasPermission('UPDATE_BUZZ')
From the GSP/taglib layer:
<sec:hasPermission permission="<permission name>">???</sec:hasPermission>
Ex: <sec:hasPermission permission="UPDATE_BUZZ">???</sec:hasPermission>
So, given those two available access checking mechanisms, and given the following controller:
class FizzController {
BuzzService BuzzService
def buzz() {
SomeData dataModel = buzzService.getModel(params)
render(view: 'buzz', model: [ dataModel: dataModel ])
}
}
...where buzz.gsp is:
<!-- Lots of HTML/GSP here -->
<g:submitButton name="update" value="Update" />
<!-- Lots more HTML/GSP down here -->
Given all that, my question is: How/where should I: (1) respond to the 'update' button's click handler, (2) perform the access check, and (3) render the error/banner/flash message? Code example (even pseudo-code) would be most awesome!
Here is what I would suggest:
Make sure your controller method is role based
Remove permission check in GSP, if the button should be visible to everyone
Create an AJAX call upon submission, if the response status is 403, display the banner.
If I were you, I'd probably try to use before-action filter in this case. In this filter I'd make a checking if current user has permissions to such an action (checking permissions should always be done in server-side, because of security reasons) and than:
if security check passes - just return true (controller will continue it's flow)
if security check fails - you can use default flash.message and return false (with propriate css style flasheed message could appears across the top of the screen with an rose/pinkish/red background)
Example code:
class UserFilters {
def filters = {
// ... other filters ...
permissionAllCheck(controller: '*', action: '*') {
before = {
doPermissionCheck(delegate)
}
}
}
private boolean doPermissionCheck(filters) {
if (! YourService.checkForPermissionForCurrentlyLoggedUser()) {
filters.flash.message = "You don't have permission to take this action"
return false
}
true
}
}
If you want to use filter only to specific controller/action, check applying section. Remember also, that you can use invert rule filter.
More info about different filterTypes.
You should also remember to add flash.message section to your layout (or selected views). You can always specify type of flash message and it's css style.
I am assuming by your question that you don't want a page refresh and perhaps not even an ajax call. Because if you did that then showing a banner is not difficult. You just want this to behave like JavaScript client-side validation (UX wise). If this assumption is wrong then don't read and use Aramiti's solution. Otherwise go ahead.
First solution
You can create a tag which takes a permission as input. Something like
<myTagLib:flashOnNoPermission permission="PERM" name="name" value="value">
</myTagLib:flashOnNoPermission>
This tag's definition can check the permission using sec:hasPermission. Then this tag can just render a template containing something like this
<hidden flash message>
<g:submitButton name="name" value="value" onclick="<unhide flash if no permission>"/>
Basically create a wrapper over grails button so that you can have flash messages alongwith buttons.
Problem
What if user's permissions are changed when user is on screen? Ajax takes care of that but this does not. Once screen is loaded then everything is fixed.
The banner is alongwith the button
Second solution
Add a common div at the top of your layout for displaying flash messages. Then create a tag similar to the above. Just don't add the flash message in the rendered template. Something like
<g:submitButton name="name" value="value" onclick="<unhide flash at top of layout if no permission>"/>
Problem
What if user's permissions are changed when he is on the screen?
Not sure why you need things onclick handler but if there is no reason just Aramiti's solution.
Best way would be to hide the button if the user has no permission to use it. That could be easily achieve through <sec:hasPermission permission="UPDATE_BUZZ">button</sec:hasPermission>
If you want button to be displayed even for user without permission, you could use the same hasPermission to add an extra class to the button. Now capture the clock event for that class using jQuery and show your message.
I'm trying to tracking this form https://secure-www.seat.com/content/lu/brand/fr/contact/arrange-a-test-drive.htx with Dynamic Tag Manager (DTM)of Adobe.
I've create a Rule Based Event like this:
Event Type --> Submit
Apply event handler directly... (In fact I try with check and uncheck)
Element Tag --> form
The same rule, with my personal page form is successful: http://pujoljulia.com/ (!Hablémos! link). As you can see I used form Tag selector, but also I tried other, button, div... and rule doesn't trigger ever.
However, in both pages the Click Map listener recognized event. Honestly I try all options and I can't see why. Can someone help me?
I'm trying to tracking this form
https://secure-www.seat.com/content/lu/brand/fr/contact/arrange-a-test-drive.htx
with Dynamic Tag Manager (DTM)of Adobe.
I took a look at your page and there it looks like DTM is not being loaded on that page. I could not find the _satellite object.
Dynamic form handlers on sites that have customized forms are fairly unstable, usually one or the other breaks. I did not look too deeply to the seat.com page, but it looks to me like JavaScript is used to override default behavior and this could be causing the problem. Clicks do get registered, but this would not solve your problems, as
What I would suggest is that you move the tracking to the next page, where the form has been submitted. This is far more reliable and has a lower chance of causing issues. Usually you can use URL parameters or page naming variables to target on these pages.
I'm trying to configure the SwitchUser feature of the Spring Security plugin and not having success. For the most part, it seems simple and strati-forward but after getting all the code in place and clicking 'switch' button, it just redirects me to default home url without making the switch.
Does anyone have more info than what already exists on the official Spring Security Core plugin site? I've been Goggling and reading everything remotely related to it and not finding any original info -- most everything is a copy of Beckwith and Talbott's original documentation.
The following is the code for my app:
Config.groovy
grails.plugins.springsecurity.useSwitchUserFilter = true
grails.plugins.springsecurity.interceptUrlMap = [
'/j_spring_security_switch_user': ['ROLE_SWITCH_USER', 'isFullyAuthenticated()'],
'/j_spring_security_exit_user': ['permitAll'],
]
I'm not sure if I should use interceptUrlMap or controllerAnnotations (?), or what criteria would determine which one to use.
The .gsp code:
<sec:ifLoggedIn>
Logged in as <sec:username/>
</sec:ifLoggedIn>
<sec:ifSwitched>
<a href='${request.contextPath}/j_spring_security_exit_user'>
Resume as <sec:switchedUserOriginalUsername/>
</a>
</sec:ifSwitched>
<sec:ifNotSwitched>
<sec:ifAllGranted roles='ROLE_SWITCH_USER'>
<form action='${request.contextPath}/j_spring_security_switch_user' method='POST'>
Switch to user: <input type='text' name='j_username'/><br/>
<input type='submit' value='Switch'/>
</form>
</sec:ifAllGranted>
</sec:ifNotSwitched>
I'm not aware of any other code or settings involved. Let me know if you need more info.
It turns out, all the code for SwitchUser was implemented correctly. Although SwitchUser still doesnt behave consistently, the problem was not with the code included in the question. We had problems with the implementation of roles in Grails.
I wish I had a better answer. I would still like to know more about SwitchUser -- more than what I've found with the Googles.
It seems like the filter only accept switching between users with the role ROLE_SWITCH_USER
I am applying spring security on my jsp page, I need to show different parts of the page to users with different roles all the roles are as following.
All authenticated users >> Edit and Add New
Admin > Delete and Edit and Add New
Anonymous > Add New
<sec:authorize
access="isAuthenticated()">
Code of add new and edit buttons
</sec:authorize>
<sec:authorize
access="hasAnyRole('ADMIN')">
Code to add new, edit and delete buttons
</sec:authorize>
<sec:authorize
access="isAnonymous()">
Code to add new
</sec:authorize>
I am wondering if there is any easier method, in this case, if I want to modify access of a specific role I have to change its access rules in security.xml file and every page that I have set the role access.
For example, lets say I want to unable Admin role to access delete button then I have to change the code of security.xml and all the JSP pages that admin role was authenticated to view delete button.
Is there any easier method to do it!?
There can be a solution by using rights set which can be contained in role object as a collection.
After this implementation you can check the right permission for showing buttons and if you want to change anything in your security architecture, you can easily manage this by granting or revoking the rights from related role.
An example of this can bee seen in the link below.
http://en.tekstenuitleg.net/blog/spring-security-with-roles-and-rights
I don't think there is a built in solution for this. You could set up a fine grained role system assinging like a edit role, a delete role and so on. Then you can assign these roles more freely.
If you want to keep it easy for the user (like still only showing admin and user role) you might have to mask the actual roles behind a mapping between the roles and the titles shown to users.
Another approach would be to set up global parameters for each action (edit, delet, etc.) in which you specify the roles that shall be allowed for the action. This way you wouldn't hardcode the roles into your application but map them through the global parameters.
Looking forward to see if someone else comes up with a better idea.
Edit to specify the approach of mapping by global parameters (refined the mapping would be stored in a db but that is getting from an ad hoc solution to implementing an ACL):
With global parameters I just meant something like a rightsMapping.properties. In this file you would map something like that:
right.edit=ROLE_USER, ROLE_ADMIN
right.edit=ROLE_ADMIN
etc...
After that you can just insert the rights into the jsf pages using something like this:
<f:loadBundle basename="rightsMapping" var="rights"/>
....
<f:CommandButton name="edit" .... rendered="hasRole(rights.edit)"/>
This is a pretty easy hands on solution which can be refined by using for example a mappings table in the DB, a Bean evaluating access rights, etc. But the basic idea of mapping the fine grained rights to the roles stays the same.
I suppose that you have the same rights for Edit buttons everywhere in your app. In this case you can extract autorization code into some custom tag (I recommend JSP tag files). For each edit button you will use your custom tag:
<customtags:hasEditPermission>
Edit button code goes here
<customtags:hasEditPermission>
All permissions will be declared once in your hasEditPermission.tag:
<%#tag description="Edit permission tag" pageEncoding="UTF-8"%>
<sec:authorize access="hasAnyRole('ADMIN')">
<jsp:doBody/>
</sec:authorize>
So in a case of new POWER_USER role you need to modify just one file:
<%#tag description="Edit permission tag" pageEncoding="UTF-8"%>
<sec:authorize access="hasAnyRole('ADMIN', 'POWER_USER')">
<jsp:doBody/>
</sec:authorize>
You can prepare and use tags for "Add new" and "Delete" buttons too. Hope this helps.
This is probably what you are looking for, with sample code
In your case, you would have BF_ADD_XXX, BF_EDIT_XXX and BF_DELETE_XXX etc.
This allows you to grant/revoke particular permissions (or BFs or business functions or whatever you want to call them) to/from particular roles.
This is a bit of a puzzle for me.
I need to capture the URI Query string passed to the Home page.
As a user travels to different pages on the web site, I have a partial view that needs that URI query string.
I need a dynamicly created link in the partial view, that equals the original call to the home page.
Example -
If the user goes to - http://www.mysite.com?mode=Joe , I need the dynamicly created link to equal - Http://www.mysite.com?mode=Joe
If the user goes to - http://www.mysite.com?mode=Tommy , I need the dynamicly created link to equal - Http://www.mysite.com?mode=Tommy
FYI - The partial view is used in the _Layout.cshtml file. the call inside - _Layout.cshtml looks like this -
#Html.Partial("MyPartial")
Thanks!
There are a number of ways to do this, but probably the simplest would be to save it to the session on your home page, and then access that session variable from your partial.
You will need to decide what to do if the session expires.
Another possible way would be to write it to a cookie on the home page request and then access the request cookie in your partial. Again, you'd need to decide on an approach for cookies disabled, or wiped out during browsing.
Alternatively, you could look at something like the approach being used in the link below to set a language across the site. Exact implementation would differ, but concept is the same:
Howto automatically add a specific value from current route to all generated links?