Grails springSecurityService injection in domain class (NULL) - grails

when I inject springSecurityService into Grails User domain class it is always null:
I tried:
def springSecurityService
static transients = ['springSecurityService']
or
def transient springSecurityService
static transients = ['springSecurityService']
but it the same, so I cannot use springSecurityService.encodePassword(password)
Any ideas? Why it's not injected?
I found a decision. I commented out the call to this() in the parameterized constructor.
User(String name, String email) {
//this()
this.name = name
this.email = email
}
and this breaks a Dependency Injection.

This is documented here (see the note starting with "Where practical, the generated domain classes include a parameterized constructor.").
You can remove the parameterized constructors if you want, but you can't use them without the this() call to the generated default constructor without losing dependency injection.
IntelliJ incorrectly flags the call to this() as invalid and I reported it as a bug in their issue tracker. It's due to be fixed for the upcoming version 15 release.

So far nothing is solved in intellij 15 EAP!
But it could be solved by simply adding a default constructor
class User implements Serializable {
private static final long serialVersionUID = 1
transient springSecurityService
String username
String password
boolean enabled = true
boolean accountExpired
boolean accountLocked
boolean passwordExpired
User() {
}
User(String username, String password) {
this()
this.username = username
this.password = password
}
...
}
Then Intellij does not bring up that error anymore.

Related

Create dynamic finder between two classes in Grails

I have two domain classes (db tables) in my Grails project:
class Doctor {
String role;
String name;
String surname;
String address;
...
#NotNull
static belongsTo = [secUser:SecUser]
....
}
class SecUser {
transient springSecurityService
String username
String password
...
}
I would like to find all SecUser that have not a correspondent Doctor.
How can I do it?
I think you need something like this:
SecUser.executeQuery(" FROM SecUser secUser WHERE NOT EXISTS (SELECT doctor.SecUser FROM Doctor doctor")

How does Spring Security differentiate between multiple logged in user

I am working on a Spring-MVC application where I am using spring security for authentication. for accessing secured functions, it is compulsory that the user is logged in. I am using a function where it can be determined whether the user is logged in or not.
I just wanted to know if the code I am posting below will hold if there are multiple users logged in at the same time, to distinguish like user A has logged in. If not, any solutions or ideas. Thank you.
Person Controller :
#Controller
public class PersonController {
private PersonService personService;
// Now whenever there are secure functions to be accessed, like below, I use it the following way :
}
#RequestMapping(value = "/note/list/{id}",method = RequestMethod.GET)
public String listNotes(#ModelAttribute("notices") Notes p,#PathVariable int id,Model model) {
Person person = personService.getCurrentlyAuthenticatedUser();
model.addAttribute("section1",this.notesService.listNotesBySectionId(1,person));
}
Get currently authenticated user function :
#Override
public Person getCurrentlyAuthenticatedUser() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String authenticatedUserId = authentication.getName();
Person person = personDAO.findPersonByUsername(authenticatedUserId);
return person;
}
I am implementing authentication this way :
#Transactional
#Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{
#Autowired private PersonDAO personDAO;
#Autowired private Assembler assembler;
private static final GrantedAuthority USER_AUTH = new SimpleGrantedAuthority("ROLE_USER");
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
Person person = personDAO.findPersonByUsername(username);
if(person == null) { throw new UsernameNotFoundException("Wrong username or password");} //Never specify which one was it exactly
return assembler.buildUserFromUserEntity(person);
}
}
Assembling the user
#Transactional
#Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{
#Autowired private PersonDAO personDAO;
#Autowired private Assembler assembler;
private static final GrantedAuthority USER_AUTH = new SimpleGrantedAuthority("ROLE_USER");
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
Person person = personDAO.findPersonByUsername(username);
if(person == null) { throw new UsernameNotFoundException("Wrong username or password");}
return assembler.buildUserFromUserEntity(person);
}
}
The SecurityContextHolder is internally implemented with a ThreadLocal. This is the default strategy spring security uses and it is proper for web applications.
Since a ThreadLocal is isolated to the scope of the current thread your code has access to the current user's information only no matter how many others are currently logged in.
In your code however you should check for null authentication objects unless you have enabled anonymous authentication.
String authenticatedUserId = authentication.getName();
authentication may be null in the line above.

#Produces for the current user object in JSF2 and JAX-RS?

I've a simple #Stateless EJB that looks like this (stripped of all logging and error handling):
#Stateless
public class CurrentUserBean {
#PersistenceContext
private EntityManager em;
#Produces #Named #LoggedIn
#SessionScoped
public User produceCurrentUser() {
Principal principal = Faces.getExternalContext().getUserPrincipal();
String username = (principal == null ? null : principal.getName());
return em.createNamedQuery("findByLogin", User.class)
.setParameter("login", username)
.getSingleResult();
}
}
Works fine when the user logs in with JSF. But the same user can also authenticate via webservice, where I can (need to?) get the user principal from SecurityContext in a bean controlled by JAX-RS (resteasy in my case):
public User doAuth(#Context SecurityContext ctx) {
return em.createNamedQuery("findByLogin", User.class)
.setParameter("login", ctx.getUserPrincial().getName())
.getSingleResult();
}
How can I unify these approaches so that the production of the current user object is the responsibility of only one class?
CDI allows you to inject the Principal directly. Just do this:
#Inject Principal userPrincipal;
And that will have the user name.

Authenticate method parameters using Spring-Security

I'm using Spring Security 3.1.4.
I have a UsersManager class as follow:
public class UsersManager {
#Secured("ROLE_ADMIN")
public void update(User user){
....
....
}
}
public class User{
Integer id;
String name;
Integer departmentId;
}
The requirement as follow:
A user is allowed to update only users from his department.
Taking in account that the User relies in the secured session, is there a way to do it with Spring Security?
You need to extend org.springframework.security.core.userdetails.User and add to it departmentId property. Then ensure that this object is used by Spring Security as principal (provide your UserDetailsService, set departmentId at the moment of login). Then you can do:
#PreAuthorize("hasRole('ROLE_ADMIN') and #principal.departmentId==#user.departmentId")
public void update(User user){

ASP.NET MVC - Ninject 2.0 Activation Error

I just started working with dependency injection for the first time and I am using as Ninject 2.0 as my IoC container in an ASP.NET MVC 2 website and I'm hitting an activation error that I am not sure how to react to. I am sure it's simple so hopefully someone can point me in the right direction without too much thought.
I have a property on my class BaseController which takes an IWebsiteSettings and is flagged with the [Inject] attribute. In my StandardKernel I load a module with the following code:
public class WebModule : Module
{
public override void Load()
{
Bind<IWebsiteSettings>()
.ToProvider(new WebsiteSettingsProvider(WebConfigurationManager.AppSettings))
.InSingletonScope();
}
}
public class WebsiteSettingsProvider : Provider<WebsiteSettings>
{
private const string WebsiteNameKey = "Website.Name";
private const string ContactFormEmailSubjectKey = "ContactForm.EmailSubject";
private const string ProductImageDirectoryKey = "Products.ImageDirectory";
private const string UploadTempDirectoryKey = "Uploads.TempDirectory";
protected NameValueCollection Settings { get; set; }
public WebsiteSettingsProvider(NameValueCollection settings)
{
Settings = settings;
}
protected override WebsiteSettings CreateInstance(IContext context)
{
return new WebsiteSettings
{
WebsiteName = Settings[WebsiteNameKey] ?? string.Empty,
ContactFormEmailSubject = Settings[ContactFormEmailSubjectKey] ?? string.Empty,
ProductImageDirectory = Settings[ProductImageDirectoryKey] ?? string.Empty,
UploadsTemporaryDirectory = Settings[UploadTempDirectoryKey] ?? string.Empty
};
}
}
This is fairly straightforward- I'm trying to load some data from the web.config file and store it in a singleton object for use across my controllers. The call to Bind seems to function exactly as it should and the Settings property in my provider is correctly initialized with the AppSettings collection in the config file. Still, when the application loads the first time:
Server Error in '/' Application.
Error activating SByte* using implicit self-binding of SByte*
No constructor was available to create an instance of the implementation type.
Activation path:
4) Injection of dependency SByte* into parameter value of constructor of type string
3) Injection of dependency string into property WebsiteName of type WebsiteSettings
2) Injection of dependency IWebsiteSettings into property WebsiteSettings of type HomeController
1) Request for HomeController
Suggestions:
1) Ensure that the implementation type has a public constructor.
2) If you have implemented the Singleton pattern, use a binding with InSingletonScope() instead.
Interestingly, if I refresh the page I don't get the exception and a call to Kernel.Get() returns the correct object.
Any advice?
(We talked about this on IRC, but I'm putting it here in case someone else runs into this problem as well.)
WebsiteSettings has [Inject] attributes on its properties, so Ninject is trying to resolve a binding from System.String to inject a value into the properties. Since you're using a custom provider to activate WebsiteSettings instances, you don't need [Inject] attributes on its properties.
The offending code was actually in the class WebsiteSettings where I was doing this:
public class WebsiteSettings : IWebsiteSettings
{
[Ninject.Inject]
public string WebsiteName
{
get; set;
}
[Ninject.Inject]
public string UploadsTemporaryDirectory
{
get; set;
}
[Ninject.Inject]
public string ContactFormEmailSubject
{
get; set;
}
[Ninject.Inject]
public string ProductImageDirectory
{
get; set;
}
}
By placing the Inject attribute on my properties I was causing Ninject to try to assign values that I never bound. Because I am using a Provider to load my type I do not need to include the Inject attribute.

Resources