Spring Security LDAP get User Given Name - spring

I am using Spring security 3.2.4 with Windows AD LDAP.
I am able to successfully authenticate and LdapUserDetailsImpl is populated.
From LdapUserDetailsImpl I can get the username, authorities, but how to get the employee name (not the login user name)
LdapUserDetailsImpl contains following properties and values
Username = 40000 ,
Enabled = true,
AccountNonExpired = true,
Dn: cn=employee name,ou=IT_FM,ou=XXX_USERS,dc=XXXX,dc=CO,dc=IN;
How do it get the employee name, Do I need to extend some class and write my own mapping or
may be simply get Dn from the principal and split the string to get the employee name.

You can just get the Dn from Principal and extract the username (cn)
LdapUserDetailsImpl ldapDetails = (LdapUserDetailsImpl) SecurityContextHolder
.getContext().getAuthentication().getPrincipal();
String dn = ldapDetails.getDn();
int beginIndex = dn.indexOf("cn=") + 3;
int endIndex = dn.indexOf(",");
String username = dn.substring(beginIndex, endIndex);

#Mukun almost has this. The only thing is, instead of:
String dn = ldapUserDetailsImpl.getDn();
int beginIndex = dn.indexOf("cn=") + 3;
int endIndex = dn.indexOf(",");
myUserDetails.setEmployeeName(dn.substring(beginIndex, endIndex));
I would have:
String name = ctx.getObjectAttribute("cn").toString()
myUserDetails.setEmployeeName(name)
This lets LDAP integration handle all the horrible stuff for you and loses the danger of chopping up strings yourself.
You might also consider
myUserDetails.setFirstName(ctx.getObjectAttribute("givenName").toString())
myUserDetails.setLastName(ctx.getObjectAttribute("sn").toString())
These things should work for both MS AD, "normal" LDAP and possible Novell too.
So the full answer would be:
#Service
public class MyUserDetailsContextMapper extends LdapUserDetailsMapper implements UserDetailsContextMapper {
#Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
LdapUserDetailsImpl ldapUserDetailsImpl = (LdapUserDetailsImpl) super.mapUserFromContext(ctx, username, authorities);
MyUserDetails myUserDetails = new MyUserDetails();
myUserDetails.setAccountNonExpired(ldapUserDetailsImpl.isAccountNonExpired());
myUserDetails.setAccountNonLocked(ldapUserDetailsImpl.isAccountNonLocked());
myUserDetails.setCredentialsNonExpired(ldapUserDetailsImpl.isCredentialsNonExpired());
myUserDetails.setEnabled(ldapUserDetailsImpl.isEnabled());
myUserDetails.setUsername(ldapUserDetailsImpl.getUsername());
myUserDetails.setAuthorities(ldapUserDetailsImpl.getAuthorities());
myUserDetails.setEmployeeName(ctx.getObjectAttribute("cn").toString());
return myUserDetails;
}
}

My Custom Mapper. Is this correct way of doing ?
#Service
public class MyUserDetailsContextMapper extends LdapUserDetailsMapper implements UserDetailsContextMapper {
#Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
LdapUserDetailsImpl ldapUserDetailsImpl = (LdapUserDetailsImpl) super.mapUserFromContext(ctx, username, authorities);
MyUserDetails myUserDetails = new MyUserDetails();
myUserDetails.setAccountNonExpired(ldapUserDetailsImpl.isAccountNonExpired());
myUserDetails.setAccountNonLocked(ldapUserDetailsImpl.isAccountNonLocked());
myUserDetails.setCredentialsNonExpired(ldapUserDetailsImpl.isCredentialsNonExpired());
myUserDetails.setEnabled(ldapUserDetailsImpl.isEnabled());
myUserDetails.setUsername(ldapUserDetailsImpl.getUsername());
myUserDetails.setAuthorities(ldapUserDetailsImpl.getAuthorities());
String dn = ldapUserDetailsImpl.getDn();
int beginIndex = dn.indexOf("cn=") + 3;
int endIndex = dn.indexOf(",");
myUserDetails.setEmployeeName(dn.substring(beginIndex, endIndex));
return myUserDetails;
}
}

Related

Extends Spring security user class

I'm Working on a Spring security project . I try to extends the security.core.userdetails.User class to add more details while registering the users.
User Extended class
public class UserDetails extends User {
private int id;
private String Country;
public UserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities, int id,
String country) {
super(username, password, authorities);
this.id = id;
Country = country;
}
public UserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities,
int id, String country) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.id = id;
Country = country;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCountry() {
return Country;
}
public void setCountry(String country) {
Country = country;
}
I have also added Id and country in my entity class(model class).
But when i try to register the user .
It give an error.org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [insert into users (username, password, enabled) values (?,?,?)]; Field 'id' doesn't have a default value; nested exception is java.sql.SQLException: Field 'id' doesn't have a default value
(The value of id and country is hard coded)
Controller class
try {
List<GrantedAuthority> authority = new ArrayList<>();
authority.add(new SimpleGrantedAuthority(form.getRole()));
String encodedPassword = passwordEncoder.encode(form.getPassword());
UserDetails details = new UserDetails(form.getUsername(), encodedPassword, authority, 10 ,"India");
System.out.println(details.getId()+" "+details.getCountry() +" "+details.getUsername());
System.out.println(details);
detailsManager.createUser(details);
}
OUPUT
10 India alpha#gmail.com
com.example.demo.model.UserDetails [Username=alpha#gmail.com, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN]]
I don't know why its is calling the parent class constructor.
The SQL is incorrect. Spring Security's INSERT by default populates the username, password, and enabled columns. However, the users table you created requires an id column as well. Since the query doesn't specify the value, it fails.
You could try extending JdbcUserDetailsManager's various methods to be aware of your id field as well. You'd need to at least extend createUser so it adds the id to the INSERT statement and findUserByUsername so it constructs your custom object.
A better way, though, would be to use Spring Data. This allows your domain object to be independent of Spring Security. Also, Spring Data has much broader SQL support.
It might be helpful to call your class something different than a Spring Security interface. So, let's imagine that your custom class (the one with the id) is called YourUser (instead of UserDetails). Now, you can wire a Spring Data-based UserDetailsService to Spring Security like so:
#Service
public class YourUserRepositoryUserDetailsService implements UserDetailsService {
private final YourUserRepository users; // your Spring Data repository
// ... constructor
#Override
public UserDetails findUserByUsername(String username) {
YourUser user = this.users.findByUsername(username)
.orElseThrow(() -> new UserNotFoundException("not found"));
return new UserDetailsAdapter(user);
}
private static class UserDetailsAdapter extends YourUser implements UserDetails {
UserDetailsAdapter(YourUser user) {
super(user); // copy constructor
}
// ... implement UserDetails methods
}
}
This UserDetailsService replaces the JdbcUserDetailsManager that you are publishing.

How to modify spring SecurityContextHolder.getContext().getAuthentication() object after successful login?

I'm working on spring boot application where i've created a CustomUserDetails class by extending UserDetails as follows..
public class CustomUserDetails
extends org.springframework.security.core.userdetails.User {
private static final long serialVersionUID = 1L;
/**
* The extra field in the login form is for the tenant name
*/
private String tenant;
private Long userId;
private String firstName;
private String middleName;
private String lastName;
private String email;
private String role;
i need to modify tenant details in UserDetails object. For this i've checked following
How to update Spring Security UserDetails impls after successful login?
https://stackanswers.net/questions/how-to-immediately-enable-the-authority-after-update-user-authority-in-spring-security
https://dev.to/onlineinterview/user-account-loginregistration-feature-with-spring-boot--3fc3
And Controller is here where i'm updating authentication object:
#PreAuthorize("hasRole('SUPER_ADMIN')")
#GetMapping(path = "/useTenant/{tenantId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<ResponseDTO> useTenant(#PathVariable Long tenantId) {
HttpStatus status = HttpStatus.OK;
boolean error = false;
String message = languageMessageService.getMessage(MultiLanguageKey.SUCCESS);
// fetch master tenant by id
Optional<MasterTenant> optional = masterTenantService.findById(tenantId);
if (optional.isPresent()) {
CustomUserDetails customUserDetails = customUserDetailsService.getUserDetail();
//Changing Tenant ID
customUserDetails.setTenant(optional.get().getTenantId());
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication instanceof UsernamePasswordAuthenticationToken) {
// Update Current user by changing tenant id in SecurityContextHolder
UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
auth.setDetails(customUserDetails);
SecurityContextHolder.getContext().setAuthentication(auth);
}
} else {
error = false;
message = languageMessageService.getMessage(MultiLanguageKey.TENANT_NOT_FOUND);
}
return new ResponseEntity<>(new ResponseDTO(error, message), status);
}
My problem is that when i'm hitting another request to perform particular action, i didn't find tenant detail in CustomUserDetails object which is fetched from
SecurityContextHolder.getContext().getAuthentication()
Please let me know how can i update or modify UserDetails object of Authentication and save back so another request get updated CustomUserDetails.
The UserDetails should be set to the Principal of the UsernamePasswordAuthenticationToken rather than Details as suggested by the java docs :
The AuthenticationManager implementation will often return an
Authentication containing richer information as the principal for use
by the application. Many of the authentication providers will create a
UserDetails object as the principal.
Details in UsernamePasswordAuthenticationToken is normally stored user 's IP address or certificate serial number etc.
So change it to :
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication instanceof UsernamePasswordAuthenticationToken) {
// Update Current user by changing tenant id in SecurityContextHolder
UsernamePasswordAuthenticationToken currentAuth = (UsernamePasswordAuthenticationToken) authentication;
CustomUserDetails userDetail = currentAuth.getPrincipal();
customUserDetails.updateTenanet("blablalb");
UsernamePasswordAuthenticationToken updateAuth = new UsernamePasswordAuthenticationToken(userDetail ,
currentAuth.getCredentials(),
currentAuth.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(updateAuth);
}

Update User's first name and last name in principal

I am updating user's information like first name and last name and I am getting first name and last name in all the pages for welcome message.
I have two controllers one for ajax request mapping and the other for normal request mapping.
Normal request mapping controller have this method. In this controller all page navigation is present and some request mapping which are not ajax calls
private String getPrincipalDisplay() {
GreenBusUser user = null;
String userName = "";
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
user = (GreenBusUser) principal;
userName = user.getFirstName() + " " + user.getLastName();
} else {
userName = "";
}
return userName;
}
This is how I am getting the username on every page by return string of this function I am adding it in ModelMap object.
When I update user's information I am doing in ajax request mapping.
#RequestMapping(value = "/restify/updateUserData", method = RequestMethod.PUT, headers = "Accept=application/json")
public ServiceResponse forgotPassword(#RequestBody Object user)
{
//logger.debug("getting response");
return setDataPut("http://localhost:7020/forgotPassword",user);
}
user is an Object type which has json data. Now how do I retrieve data from object and update my first name and last name in principal.
This is my GreenBusUser class
public class GreenBusUser implements UserDetails
{
private static final long serialVersionUID = 1L;
private String username;
private String password;
private Collection<? extends GrantedAuthority> grantedAuthorities;
private String firstName;
private String lastName;
public GreenBusUser(String username,String password,Collection<? extends GrantedAuthority> authorities,String firstName, String lastName)
{
this.username = username;
this.password = password;
this.grantedAuthorities = authorities;
this.firstName=firstName;
this.lastName=lastName;
this.grantedAuthorities.stream().forEach(System.out::println);
}
public Collection<? extends GrantedAuthority> getAuthorities()
{
return grantedAuthorities;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getPassword()
{
return password;
}
public String getUsername()
{
return username;
}
public boolean isAccountNonExpired()
{
return true;
}
public boolean isAccountNonLocked()
{
return true;
}
public boolean isCredentialsNonExpired()
{
return true;
}
public boolean isEnabled()
{
return true;
}
}
UPDATE:::::
I have updated your code and applied some part of your answer into mine but still I ran into a problem
#RequestMapping(value="/updateUser",method=RequestMethod.GET)
public String updateUser(ModelMap model) {
UserInfo user = getUserObject();
GreenBusUser newGreenBususer = null;
List<User> list = new ArrayList<User>();
list = FetchDataService.fetchDataUser("http://localhost:8060/GetuserbyUserName?username=" + getPrincipal(), user.getUsername(), user.getPassword());
logger.debug("new user list ----->>>"+list.size());
User newuser=(User)list.get(0);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
SecurityContextHolder.getContext().getAuthentication().getPrincipal(), SecurityContextHolder.getContext().getAuthentication().getCredentials());
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
newGreenBususer=(GreenBusUser)principal;
logger.debug("newGreenBususerDetails---->>>"+newGreenBususer.toString());
newGreenBususer.setFirstName(newuser.getFirstName());
newGreenBususer.setLastName(newuser.getLastName());
if(newGreenBususer.getFirstName()!=null) {
logger.debug("got my first name");
}
if(newGreenBususer.getLastName()!=null) {
logger.debug("got my last name");
}
auth.setDetails(newGreenBususer);
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(auth);
SecurityContextHolder.setContext(context);
model.addAttribute("user", getPrincipalDisplay());
model.addAttribute("userData", list);
model.addAttribute("check", true);
return "GreenBus_updateProfile_User";
}
At first it sets the firstname and lastname to GreenBusUser and then there is setDetails method when I reload the page it says No user found when I am calling getUserObject() method at the top of this method.
private X2CUser getUserObject() {
X2CUser userName = null;
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
userName = ((X2CUser) principal);
} else {
logger.info("No user found");
}
return userName;
}
If you are updating the password, then it will be good to logout the user and tell him to relogin.
Try this code .. It might help you.
UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(user, pass);
Authentication auth = authManager.authenticate(authReq);
SecurityContext sc = SecurityContextHolder.getContext();
securityContext.setAuthentication(auth);
I have finally resolved my problem though I have later added some code in my question part in UPDATE section.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
newGreenBususer=(GreenBusUser)principal;
newGreenBususer.setFirstName(newuser.getFirstName());
newGreenBususer.setLastName(newuser.getLastName());
Yes that's all need to be done.
This part--->>
auth.setDetails(newGreenBususer);
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(auth);
SecurityContextHolder.setContext(context);
set new context making security pointing to null when I reload still not clear because I am setting the details before reload so its like I get new context but I have set the new user details.
Though I have finally resolved my problem but if anyone could shed some light why it was happening then I will accept his/her answer.
Thanks alot for your support. Keep Learning!

How to use InetOrgPersonContextMapper class

I'm authenticated and authorise to Active Directory by Spring Security.
But can not retrive LDAP attributes, for example MAIL.
I trying use InetOrgPersonContextMapper for it...
#Bean
public InetOrgPersonContextMapper inetOrgPersonContextMapper(){
InetOrgPersonContextMapper contextMapper = new InetOrgPersonContextMapper();
return contextMapper;
}
#Bean
public LdapAuthenticationProvider ldapAuthenticationProvider(){
LdapAuthenticationProvider ldapAuthenticationProvider = new LdapAuthenticationProvider(ldapAuthenticator(),ldapAuthoritiesPopulator());
ldapAuthenticationProvider.setUserDetailsContextMapper(inetOrgPersonContextMapper());
return ldapAuthenticationProvider;
}
but when i trying retrive attributes in controller to i get ClassCastExeption
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
InetOrgPerson person = (InetOrgPerson)auth.getPrincipal();
Please tell me correct way for reitrive attributes.
I guess it's no better way, but it's working.
If anybody know how can do it better, please tell me.
#Bean
public UserDetailsContextMapper userDetailsContextMapper(){
return new LdapUserDetailsMapper(){
#Override
public UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<? extends GrantedAuthority> authorities) {
InetOrgPersonContextMapper personContextMapper = new InetOrgPersonContextMapper();
UserDetails cm = personContextMapper.mapUserFromContext(ctx,username,authorities);
String MAIL = ((InetOrgPerson)(personContextMapper.mapUserFromContext(ctx,username,authorities))).getMail();
String FullName = ((InetOrgPerson)(personContextMapper.mapUserFromContext(ctx,username,authorities))).getDisplayName();
System.out.println("MAIL: " + MAIL + " Full Name: " + FullName);
return cm;
}
};
}

Spring security, how to restrict user access certain resources based on dynamic roles?

given a scenario , there is a HTML contents OR some method in a controller, which only allow to be access by "a" role.
from above, we achieve by using #hasRole("a")
However, in my case, the role is dynamic:
Example, admin add a new role "b", and able to be access these content.
So how to do it?
I tried ACL, but that's only protect the domain object with an id.
there is an annotation called hasAuthority, but i cant search
anythings from internet.
there is an ObjectIdentityImpl, not really
how to implement.
EDIT: my solution
After study, ACL is more on secure list of object.
Example: u want to secure staff table, some staff record(like CEO,manager) are only accessible by higher management. the rest of staff record are view-able by all. This is what ACL to do.
However, when we need to protect some method,controller,url,static content.... the ACL is not suitable for this. we need to use hasAuthority or hasPermission or hasRole or ......
In some web systems, there are only few roles, admin and user. For this case, hasAuthority or hasRole is quite enough for this. u just annotate #hasRole('admin') for the resources u want to protect.
However,in some systems, there are dynamic role, for example: admin create a new role "temporary_user", but the contoller or method is annotate by #hasRole('user'), which not accessible by "temporary_user".
in this case, based on my understanding, there are few ways to do.
create many roles based on how many resources u want to protect. for example: assign 'role_getRecord' to getRecords(),assign 'role_writeRecord' to writeRecord(). this is a way to do without changing spring security mechanism, but will have a lot of roles on your database table, and more complex system, will have more.
#hasPermission - this is what i use right now. i create a CustomGrantedAuthority, in order to have more flexible implementation. and i do have a CustomUserDetailsService and CustomSpringSecurityUser, when user login will create CustomSpringSecurityUser with collection of CustomGrantedAuthority then return CustomSpringSecurityUser to CustomUserDetailsService. and also i do have a CustomPermission to verify the permission.
Please vote UP, if your think is useful, and please comment if i wrong or does havea better way to do it.
here is my code
CustomSpringSecurityUser
public class CustomSpringSecurityUser implements UserDetails, CredentialsContainer {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private String password;
private final String username;
private final Set<GrantedAuthority> authorities;
private final boolean accountNonExpired;
private final boolean accountNonLocked;
private final boolean credentialsNonExpired;
private final boolean enabled;
public CustomSpringSecurityUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
this(username, password, true, true, true, true, authorities);
}
public CustomSpringSecurityUser(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
if (((username == null) || "".equals(username)) || (password == null)) {
throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
}
this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpired = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
// this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
this.authorities = new HashSet<GrantedAuthority>(authorities);
}
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}
public String getPassword() {
return password;
}
public String getUsername() {
return username;
}
public boolean isEnabled() {
return enabled;
}
public boolean isAccountNonExpired() {
return accountNonExpired;
}
public boolean isAccountNonLocked() {
return accountNonLocked;
}
public boolean isCredentialsNonExpired() {
return credentialsNonExpired;
}
public void eraseCredentials() {
password = null;
}
private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
SortedSet<GrantedAuthority> sortedAuthorities =
new TreeSet<GrantedAuthority>(new AuthorityComparator());
for (GrantedAuthority grantedAuthority : authorities) {
Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
sortedAuthorities.add(grantedAuthority);
}
return sortedAuthorities;
}
private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
public int compare(GrantedAuthority g1, GrantedAuthority g2) {
if (g2.getAuthority() == null) {
return -1;
}
if (g1.getAuthority() == null) {
return 1;
}
return g1.getAuthority().compareTo(g2.getAuthority());
}
}
#Override
public boolean equals(Object rhs) {
if (rhs instanceof CustomSpringSecurityUser) {
return username.equals(((CustomSpringSecurityUser) rhs).username);
}
return false;
}
#Override
public int hashCode() {
return username.hashCode();
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString()).append(": ");
sb.append("Username: ").append(this.username).append("; ");
sb.append("Password: [PROTECTED]; ");
sb.append("Enabled: ").append(this.enabled).append("; ");
sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
if (!authorities.isEmpty()) {
sb.append("Granted Authorities: ");
boolean first = true;
for (GrantedAuthority auth : authorities) {
if (!first) {
sb.append(",");
}
first = false;
sb.append(auth);
}
} else {
sb.append("Not granted any authorities");
}
return sb.toString();
}
}
CustomGrantedAuthority
public class CustomGrantedAuthority implements GrantedAuthority{
private String role;
private String permission,action;
public String getPermission() {
return permission;
}
public void setPermission(String permission) {
this.permission = permission;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
#Override
public String getAuthority() {
return role;
}
}
CustomeUserDetailsService
#Service
#Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private OcUserService userService;
private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class);
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
sg.com.xx.xx.table.OcUser u = userService.findByLoginname(username);
String pass = sg.com.xx.xx.table.OcUser.byteToHex(u.getPassword());
Collection<? extends GrantedAuthority> permissionList = userService.getPermissionByUserId(u.getId());
boolean enabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
CustomSpringSecurityUser user = new CustomSpringSecurityUser(u.getLoginname(),
pass,
enabled,
accountNonExpired,
credentialsNonExpired,
accountNonLocked,
permissionList);
return user;
} catch (Exception e) {
logger.error("==============================================");
logger.error(e.toString());
return null;
}
}
}
CustomPermission
public class CustomPermission implements PermissionEvaluator {
#Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
Collection<? extends GrantedAuthority> x = authentication.getAuthorities();
for(Object o : x)
{
CustomGrantedAuthority y = (CustomGrantedAuthority) o ;
if(y.getPermission().equals(targetDomainObject) )
if( y.getAction().equals(permission) )
return true;
}
return false;
}
#Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
int a = 5;
return true;
}
}
I don't know what you mean under resources, but I found that the best way to work with it in spring, is to grant users permissions (authorities) instead of roles, you still have roles, but they are there just to bundle up the permissions. After this is set up, you assign actual permissions for your views and methods. I found a data model here:
http://springinpractice.com/2010/10/27/quick-tip-spring-security-role-based-authorization-and-permissions/
What if you use Java Reflection to get every controller method, then you asign any of these methods to role relation to build a "dynamic role"? This way you could add or remove any action to any role at any moment. Maybe Spring Security is not required this way.

Resources