2012-07-17 43 views
0

我一直无法弄清楚我在这里做错了什么。我试图访问页面/user/test.jsp,但我有一个错误403访问被拒绝的错误。错误403 - 使用Spring安全拒绝访问 - ManyToMany注释问题?

我想问题来自UserEntity类中的ManyToMany注释。我尝试了所有可能的方法,但在解决这个问题上仍然不成功。

经过进一步研究,看起来user_security_role没有从DB加载。

我知道这是因为在buildUserFromUserEntity在汇编类下面的代码部分的情况下返回一个空SecurityRoleCollection:

for (SecurityRoleEntity role : userEntity.getSecurityRoleCollection()) { 
    authorities.add(new GrantedAuthorityImpl(role.getName())); 
} 

下面是我用于表的SQL(从教程):

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; 

这里是棘手的部分我不能让工作: 用于专用集securityRoleCollection的注释;属性不从数据库加载数据,我无法弄清楚我在这里做错了什么。

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() { 

    } 

这里是我UserEntityDAOImpl类:

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; 
    } 

这里是SecurityRoleEntity类:

@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... 

这里是汇编类:

@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; 

    } 

} 

这里是内容我的spring-security.xml :

<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> 

这里是UserDetailsS​​erviceImpl:

@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); 

    } 

} 

这里是我试图访问该页面的控制器:

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"); 
} 

} 

我一直在关注这个教程: http://giannisapi.wordpress.com/2011/09/21/spring-3-spring-security-implementing-custom-userdetails-with-hibernate/

这就是说插入那些rol ES:

insert into security_role(name) values ("ROLE_admin"); 

insert into security_role(name) values ("ROLE_User"); 

我认为插在DB角色的名称应该是一样的一个在配置文件中配置的,所以我改变了一个在XML文件,以适应一个在DB但它不会改变任何东西。

DB中的所有其他数据似乎都很好。

我还验证了我尝试访问的页面在/ user中,并且是这种情况。

+0

它们的确需要匹配值 - 如果您使用正确的(匹配)值更新帖子,测试该值并包含您在日志中看到的任何堆栈跟踪,它可能会更清晰。同时检查您是否可以成功访问该页面_without_安全配置。 – MattR 2012-07-18 00:49:54

+0

我更新了我的帖子,提供了更多信息。我终于找到问题的来源,但无法弄清楚我做错了什么。看来我的UserEntity类不会从数据库加载user_security_role。 UserSecurityRole的集合没有被填写。 – dukable 2012-07-18 01:45:15

回答

0

我有(除非SecurityRoleEntity类是两者之间的映射?)能够解决问题。这是我的错,我没有在hibernate.cfg.xml文件下使用好的数据库。

这里配置的数据库引用了另一个数据库,其中我也有3个表,但因为它们是空的,所以没有任何角色被hibernate请求选中。

0

当您调用UserEntityDAO时,您的UserEntity的securityRoleCollection未被抓取。 findByName()。你要么需要实现你的DAO所以它做了一个连接获取查询(可能更有效)或者简单的解决方法是添加:

@ManyToMany(fetch = FetchType.EAGER) 
private Set<SecurityRoleEntity> securityRoleCollection 

我不认为这是你唯一的问题虽然。你还需要确保所有的角色名是相等的 - 你的代码上面目前有:

ROLE_REGISTERED_USER 
ROLE_User 

他们需要同

+0

谢谢,它解决了LazyInitializationException,但我知道我有最初的错误:HTTP状态403 - 访问被拒绝。仔细一看,似乎在Assembler类的buildUserFromUserEntity()方法中为(SecurityRoleEntity角色:userEntity.getSecurityRoleCollection())返回一个空的Set of SecurityRoleCollection – dukable 2012-07-18 02:23:22

+0

我还修复了角色名称使它们相等,我只是忘记了更新帖子。 – dukable 2012-07-18 02:24:57

+0

你不显示那个类,但它听起来像它也需要一个FetchType.EAGER(或联合提取查询) – MattR 2012-07-18 02:31:59