I'm using Grails Spring Security Core plugin and I need to perform a few actions when logout happens such as delete some class instances related to the user. I tried the following code:
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import grails.plugins.springsecurity.Secured
class LogoutController {
def index = {
def currentUser = currentUser()
currentUser.searchedResults.each{searched->
def searchInstance = Search.get(searched.searchId)
searchInstance.delete()
}
redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl // '/j_spring_security_logout'
}
private currentUser(){
return User.get(springSecurityService.principal.id)
}
}
However Grails is giving the error: No such property: User for class: LogoutController
My guess is that this is happening because when I installed Spring security core plugin, the LogoutController and LoginController were created in a different package called "default package". Is there any way to overcome this issue? Any help would be appreciated! Thanks
You simply need to import the User class. Something like:
import mypackage.User
Related
I recently posted a question about multiple data sources. Things were going well until I hit this issue:
Controller
def doSomething() {
def user=userService.getCurrentUser()
}
Service
class UserService {
def getCurrentUser() {
def principal = springSecurityService.principal
String username = principal.username
return find(username)
}
def find(String user) {
return User.find{username==user}
}
}
This had been working previously on single DataSource but now with both enabled I see this on the browser:
Error 500: Internal Server Error URI /xxx/xxx Class
org.springframework.beans.factory.NoUniqueBeanDefinitionException
Message No qualifying bean of type
[org.springframework.transaction.PlatformTransactionManager] is
defined: expected single matching bean but found 3:
transactionManager,transactionManager_countrycity,$primaryTransactionManager
Okay this is now resolved.
I think I found the issue: under grails 3 with multiple data sources if you have this import :
import org.springframework.transaction.annotation.Transactional
You will run into the above problems:
If you how ever have :
import grails.transaction.Transactional
things will work as expected. I hadn;t paid attention and let ide choose wrong declaration
I use spring security core plugin. I want to put an object in session just after user has logged in. What I've discovered so far is that there is grails.plugin.springsecurity.LoginController in the plugin. And it has method which is called ajaxSuccess which seems to be invoked just after successfull authentication. So I decided to create another LoginController which extends default one and overrides this method:
#Secured('permitAll')
class LoginController extends grails.plugin.springsecurity.LoginController {
def ajaxSuccess() {
session['somevproperty'] = someValue
super.ajaxSuccess()
}
}
but debugging shows that this method is never invoked. What is going wrong? May there is another way to do what I want? Thank you!
Spring security has it own event listeners. I prefer you use that.
http://grails-plugins.github.io/grails-spring-security-core/guide/events.html
Sample code from above link for success login.
package com.foo.bar
import org.springframework.context.ApplicationListener
import org.springframework.security.authentication.event. AuthenticationSuccessEvent
class MySecurityEventListener implements ApplicationListener<AuthenticationSuccessEvent> {
void onApplicationEvent(AuthenticationSuccessEvent event) {
// handle the event
}
}
I have upgraded My Spring security plugin from spring-security-core:1.2.7.2 to spring-security-core:2.0-RC2 and my application is using Grails 2.3.7.
After upgrade I changed the imports accordingly so all compilation error got fixed but after running my application when I tried to access it http://localhost:8080/login/auth I got exception like :
Caused by: groovy.lang.MissingPropertyException: No such property: id for class: org.springframework.security.core.userdetails.User
as auth.gsp is using custom tag lib and code is like
if(springSecurityService.principal!="anonymousUser")user = SecUser.get(springSecurityService.principal.id)
here it is saying No such property: id for class: org.springframework.security.core.userdetails.User
Not sure how to fix this problem ...
Until i can see what you want is to retrieve current logged user id, there is a special helper that only get the user id "loadCurrentUser()"
i paste this code from grails spring security core plugin in section loadCurrentUser()
class SomeController {
def springSecurityService
def someAction() {
def user = springSecurityService.isLoggedIn() ? springSecurityService.loadCurrentUser() : null
if (user) {
CreditCard card = CreditCard.findByIdAndUser(params.id as Long, user)
…
}
…
}
}
i hope it is usefull
I have used Spring Security Core plugin in my grails application, and I want to add the functionality:
When a user is already logged in, user will not be allowed to use same userName and password to login again using a different browser or a different machine altogether.
I think it should be somewhere in the spring security core but not sure.
It can be done using some configuration settings:
on the config.groovy, add this line:
grails.plugins.springsecurity.useHttpSessionEventPublisher = true
On the bootstrap.groovy:
import these two packages:
import org.codehaus.groovy.grails.plugins.springsecurity.SecurityFilterPosition
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
Then few dependency injections:
def authenticationManager
def concurrentSessionController
def securityContextPersistenceFilter
def authenticationProcessingFilter
def concurrentSessionControlStrategy
then register concurrency filter inside init(In Bootstrap):
authenticationProcessingFilter.sessionAuthenticationStrategy = concurrentSessionControlStrategy
SpringSecurityUtils.clientRegisterFilter('concurrencyFilter', SecurityFilterPosition.CONCURRENT_SESSION_FILTER)
and at the end in the resources.groovy:
import few packages:
import org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy
import org.springframework.security.web.session.ConcurrentSessionFilter
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
then inside beans add:
sessionRegistry(SessionRegistryImpl)
concurrencyFilter(ConcurrentSessionFilter) {
sessionRegistry = sessionRegistry
logoutHandlers = [ref("rememberMeServices"), ref("securityContextLogoutHandler")]
expiredUrl='/login/concurrentSession'
}
concurrentSessionControlStrategy(ConcurrentSessionControlStrategy, sessionRegistry) {
alwaysCreateSession = true
exceptionIfMaximumExceeded = true
maximumSessions = 1
}
and done, now user can login only from one place.
I didn't tried it with the rememberMe option.
You can try using Persistent Logins and Remember-Me Cookie. The idea is to persist the remember-me token in database and check whether a cookie is present in the database or not in subsequent login attempts. If a cookie is present then disallow the login.
This has to work in conjunction with the key rememberMe.tokenValiditySeconds so that the token expires and is purged from the database.
You would get more insight and throw some light to this scenario if you look at
How to Create Persistent Token
Best Practices in Persistent Login
Remember-Me in Spring
I am trying to use the commentable plugin with Spring Security.
I can't manage to write the right
grails.commentable.poster.evaluator
I tried {User.get(springSecurityService.principal.id)},
but from the CommentController, both User and springSecurity seems unaccessible.
What should I do?
For springSecurityService.principal.id since there's no dependency injection field for springSecurityService it can't work, so you need to call what springSecurityService.principal.id calls - org.springframework.security.core.context.SecurityContextHolder.context.authentication.principal.id
To fix the problem with User, you'll need the full class name with package. So combined, this should be
{com.yourcompany.yourapp.User.get(org.springframework.security.core.context.SecurityContextHolder.context.authentication.principal.id)}
I adapted Burt's answer such that it doesn't throw an exception if nobody is logged in
grails.commentable.poster.evaluator = {
def principal = org.springframework.security.core.context.SecurityContextHolder.context.authentication?.principal
if (principal?.hasProperty('id')) {
def currentUserId = principal.id
if (currentUserId) {
com.yourcompany.yourapp.User.get(currentUserId)
}
}
}