I haven't been able to figure out what I am doing wrong here. I am trying to access the page /user/test.jsp but I am having an error 403 access denied error.
I guess the problem is coming from the ManyToMany annotations in the UserEntity class. I have tried everything I could but am still not successful in solving this.
After further research, it appears that the user_security_role are not loaded from the DB.
I know it is the case since the following portion of code in the buildUserFromUserEntity in the Assembler class return an empty SecurityRoleCollection:
Here are the SQL I used for the table (from the tutorial):
Here is the tricky part I can't get to work:
The annotations configured for the private Set securityRoleCollection; attribute do not load the data from the DB, I can't figure out what I am doing wrong here.
Here is my UserEntityDAOImpl class:
Here is the SecurityRoleEntity class:
Here is the assembler class:
Here is the content of my spring-security.xml:
Here is the UserDetailsServiceImpl:
Here is the controller of the page I am trying to access:
I have been following this tutorial:
<a href="http://giannisapi.wordpress.com/201...plementing-custom-userdetails-with-hibernate/" rel="nofollow">http://giannisapi.wordpress.com/201...plementing-custom-userdetails-with-hibernate/</a>
Which says to insert those roles:
I thought that the name of the role inserted in the DB should be the same as the one configured in the config file, so I changed the one in the xml file to fit the one in the DB but it doesn't change anything.
All other data in the DB seems to be good.
I also verified that the page I am trying to access is in /user and it is the case.
I guess the problem is coming from the ManyToMany annotations in the UserEntity class. I have tried everything I could but am still not successful in solving this.
After further research, it appears that the user_security_role are not loaded from the DB.
I know it is the case since the following portion of code in the buildUserFromUserEntity in the Assembler class return an empty SecurityRoleCollection:
Code:
for (SecurityRoleEntity role : userEntity.getSecurityRoleCollection()) {
authorities.add(new GrantedAuthorityImpl(role.getName()));
}
Here are the SQL I used for the table (from the tutorial):
Code:
CREATE TABLE IF NOT EXISTS security_role (
`id` INT(11) NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(50) NULL DEFAULT NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB
AUTO_INCREMENT = 4
DEFAULT CHARACTER SET = latin1;
CREATE TABLE IF NOT EXISTS user (
`id` INT(11) NOT NULL AUTO_INCREMENT ,
`first_name` VARCHAR(45) NULL DEFAULT NULL ,
`family_name` VARCHAR(45) NULL DEFAULT NULL ,
`dob` DATE NULL DEFAULT NULL ,
`password` VARCHAR(45) NOT NULL ,
`username` VARCHAR(45) NOT NULL ,
`confirm_password` VARCHAR(45) NOT NULL ,
`active` TINYINT(1) NOT NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `username` (`username` ASC) )
ENGINE = InnoDB
AUTO_INCREMENT = 9
DEFAULT CHARACTER SET = latin1;
CREATE TABLE IF NOT EXISTS user_security_role (
`user_id` INT(11) NOT NULL ,
`security_role_id` INT(11) NOT NULL ,
PRIMARY KEY (`user_id`, `security_role_id`) ,
INDEX `security_role_id` (`security_role_id` ASC) ,
CONSTRAINT `user_security_role_ibfk_1`
FOREIGN KEY (`user_id` )
REFERENCES `user` (`id` ),
CONSTRAINT `user_security_role_ibfk_2`
FOREIGN KEY (`security_role_id` )
REFERENCES `security_role` (`id` ))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1;
Here is the tricky part I can't get to work:
The annotations configured for the private Set securityRoleCollection; attribute do not load the data from the DB, I can't figure out what I am doing wrong here.
Code:
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Column(name = "first_name")
private String firstName;
@Column(name = "family_name")
private String familyName;
@Column(name = "dob")
@Temporal(TemporalType.DATE)
private Date dob;
@Basic(optional = false)
@Column(name = "password")
private String password;
@Basic(optional = false)
@Column(name = "username")
private String username;
@Basic(optional = false)
@Column(name = "confirm_password")
private String confirmPassword;
@Basic(optional = false)
@Column(name = "active")
private boolean active;
@JoinTable(name = "user_security_role", joinColumns = {
@JoinColumn(name = "user_id", referencedColumnName = "id") }, inverseJoinColumns = {
@JoinColumn(name = "security_role_id", referencedColumnName = "id") })
@ManyToMany
private Set<SecurityRoleEntity> securityRoleCollection;
public UserEntity() {
}
Here is my UserEntityDAOImpl class:
Code:
public class UserEntityDAOImpl implements UserEntityDAO {
public UserEntity findByName(String username) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction transaction = null;
UserEntity user = null;
try {
transaction = session.beginTransaction();
user = (UserEntity)session.createQuery("select u from UserEntity u where u.username = '"
+ username + "'").uniqueResult();
transaction.commit();
} catch (HibernateException e) {
transaction.rollback();
e.printStackTrace();
} finally {
session.close();
}
return user;
}
Here is the SecurityRoleEntity class:
Code:
@Entity
@Table(name = "security_role", catalog = "userauth", schema = "")
@NamedQueries({
@NamedQuery(name = "SecurityRoleEntity.findAll", query = "SELECT s FROM SecurityRoleEntity s"),
@NamedQuery(name = "SecurityRoleEntity.findById", query = "SELECT s FROM SecurityRoleEntity s WHERE s.id = :id"),
@NamedQuery(name = "SecurityRoleEntity.findByName", query = "SELECT s FROM SecurityRoleEntity s WHERE s.name = :name") })
public class SecurityRoleEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
@ManyToMany(mappedBy = "securityRoleCollection", fetch = FetchType.EAGER)
private List<UserEntity> userCollection;
public SecurityRoleEntity() {
}
getters and setters...
Here is the assembler class:
Code:
@Service("assembler")
public class Assembler {
@Transactional(readOnly = true)
User buildUserFromUserEntity(UserEntity userEntity) {
String username = userEntity.getUsername();
String password = userEntity.getPassword();
boolean enabled = userEntity.getActive();
boolean accountNonExpired = userEntity.getActive();
boolean credentialsNonExpired = userEntity.getActive();
boolean accountNonLocked = userEntity.getActive();
Collection<GrantedAuthorityImpl> authorities = new ArrayList<GrantedAuthorityImpl>();
for (SecurityRoleEntity role : userEntity.getSecurityRoleCollection()) {
authorities.add(new GrantedAuthorityImpl(role.getName()));
}
User user = new User(username, password, enabled,
accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
return user;
}
}
Here is the content of my spring-security.xml:
Code:
<beans:bean id="userDetailsService" class="service.UserDetailsServiceImpl">
</beans:bean>
<beans:bean id="assembler" class="service.Assembler">
</beans:bean>
<!-- <context:component-scan base-package="org.intan.pedigree" /> -->
<http auto-config='true'>
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<intercept-url pattern="/user/**" access="ROLE_User" />
<!-- <security:intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"
/> -->
</http>
<beans:bean id="daoAuthenticationProvider"
class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<beans:property name="userDetailsService" ref="userDetailsService" />
</beans:bean>
<beans:bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<beans:property name="providers">
<beans:list>
<beans:ref local="daoAuthenticationProvider" />
</beans:list>
</beans:property>
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
<password-encoder hash="plaintext" />
</authentication-provider>
</authentication-manager>
Here is the UserDetailsServiceImpl:
Code:
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserEntityDAO dao;
@Autowired
private Assembler assembler;
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
UserDetails userDetails = null;
UserEntity userEntity = dao.findByName(username);
if (userEntity == null)
throw new UsernameNotFoundException("user not found");
return assembler.buildUserFromUserEntity(userEntity);
}
}
Here is the controller of the page I am trying to access:
Code:
public class HowDoesItWorkController implements Controller {
protected final Log logger = LogFactory.getLog(getClass());
@PreAuthorize("hasRole('ROLE_User')")
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
logger.info("returning contact view");
return new ModelAndView("/explain");
}
}
I have been following this tutorial:
<a href="http://giannisapi.wordpress.com/201...plementing-custom-userdetails-with-hibernate/" rel="nofollow">http://giannisapi.wordpress.com/201...plementing-custom-userdetails-with-hibernate/</a>
Which says to insert those roles:
Code:
insert into security_role(name) values ("ROLE_admin");
insert into security_role(name) values ("ROLE_User");
I thought that the name of the role inserted in the DB should be the same as the one configured in the config file, so I changed the one in the xml file to fit the one in the DB but it doesn't change anything.
All other data in the DB seems to be good.
I also verified that the page I am trying to access is in /user and it is the case.