I have a web application with Spring MVC 3.2 and Spring Security 3.1
I'm using roles base security and have implemented UserDetailsService and UserDetails to provide GrantedAuthority.
I've enabled global method security with jsr250-annotations
Everything upto here is working as expected with signed in user method access restricted to the declared roles.
I have a further requirement to run certain methods called during application initialisation as a special user with a 'system role' ideally along the lines of JavaEE RunAs.
I'm not sure how to do this in Spring Security.
Should I be trying to create a PreAuthenticatedAuthenticationToken
with some made up values and a 'system role' authority.
I could then do something likeSecurityContextHolder.getContext().setAuthentication(token);
when initialising the application.
Alternatively should I be trying to use the RunAsManager. It sounds like what I need but I have not found any simple examples of how I actually could use it.
I'm fairly new to Spring Security and I'm unsure of the best way to proceed.
When my application starts
- I run a post construct method in my spring bean to create a special user in memory with a system role.
- This user object implements the
org.springframework.security.core.userdetails.UserDetails
interface.
- I then use the user to create a security token
org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
The token is then set in the Security Context.
@Service
@Transactional(readOnly = true)
public class ApplicationConfiguration{
@Inject
MyService myService;
@PostConstruct
@Transactional(readOnly = false)
public void init(){
// ######## Application Starting #######"
// Create a user that meets the contract of the Spring UserDetails interface
UserAccountImpl sysAcc = new UserAccountImpl("system", "system", "system");
UserRole role = new UserRole(Role.SYSTEM_ROLE);
role.addUserPermission(Permission.SYSTEM);
sysAcc.addUserRole(role);
UserDetailsAdapter userDetails = new UserDetailsAdapter(sysAcc);
// Create a token and set the security context
PreAuthenticatedAuthenticationToken token = new PreAuthenticatedAuthenticationToken( userDetails, userDetails.getPassword(), userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(token);
// Now call service method with roles allowed
myService.initialiseSystem();
}
}
....
public interface MyService {
@RolesAllowed(SYSTEM)
public void initialiseSystem();
}
Do you really need to attach a role to the said app initialization? Why not just extract the code that needs to be run during initialization like so:
public interface Service {
@Secured("hasRole('USER')")
void service();
}
public class DefaultService implements Service {
@Override
public void service() {
doService();
}
public void doService() {
// Implementation here
}
}
...
public class AppInitializer {
@Autowired
private DefaultService service;
public void init() {
service.doService();
}
}
I believe that in this case a good solution for you would be to use the Spring Security OAuth because allow you have a greater integration to custom rules for access via tokens.
http://projects.spring.io/spring-security-oauth/