0

我一直在为 spring MVC + Spring Security + hibernate 制作一个登录页面的示例,但现在我遇到了一个问题,@Autowire即不断给我空值的燃料。服务器没有报告任何错误,只是它没有完成操作。

CustomUserDetailsS​​ervice.java

package com.carloscortina.paidosSimple.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import com.carloscortina.paidosSimple.dao.UsuarioDao;
import com.carloscortina.paidosSimple.model.Usuario;

@Service
@Transactional(readOnly=true)
public class CustomUserDetailsService implements UserDetailsService {

    private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class);

    @Autowired UsuarioDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {

        logger.info(username);
        Usuario domainUser = userDao.getUsuario(username);
        logger.info(domainUser.getUsername());

        boolean enabled = true;
        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        return new User(
            domainUser.getUsername(),
            domainUser.getPassword(),
            enabled,
            accountNonExpired,
            credentialsNonExpired,
            accountNonLocked,
            getAuthorities(domainUser.getRol().getId()));
    }

    public Collection<? extends GrantedAuthority> getAuthorities(Integer rol){
        List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(rol));
        return authList;
    }

    public List<String> getRoles(Integer rol){
        List<String> roles = new ArrayList<String>();

        if(rol.intValue() == 1){
            roles.add("ROLE_DOCTOR");
            roles.add("ROLE_ASISTENTE");
        }else if (rol.intValue() == 2){
            roles.add("ROLE_ASISTENTE");
        }
        return roles;
    }

    public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles){
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

        for (String role : roles) {
            authorities.add(new SimpleGrantedAuthority(role));
        }
        return authorities;

    }

}

此处该字段userDao保持为空,因此当我尝试使用userDao.getUsuario(username)该操作时,它不会继续,它不会报告错误或类似情况,它只会给我一个 404- 错误

UsuarioDao.xml

package com.carloscortina.paidosSimple.dao;

import java.util.ArrayList;
import java.util.List;


import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.carloscortina.paidosSimple.model.Usuario;

@Repository
public class UsuarioDaoImp implements UsuarioDao {

    private static final Logger logger = LoggerFactory.getLogger(UsuarioDaoImp.class);

    @Autowired
    private SessionFactory sessionFactory;

    private Session getCurrentSession(){
        return sessionFactory.getCurrentSession();
    }

    @Override
    public Usuario getUsuario(String username) {
        logger.debug("probando");
        List<Usuario> userList = new ArrayList<Usuario>();
        Query query = getCurrentSession().createQuery("from Usuario u where u.Username = :username");
        query.setParameter("username", username);
        userList = query.list();
        if (userList.size() > 0){
            return (Usuario) userList.get(0);
        }else{
            return null;
        }
    }

}

servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Enable transaction Manager -->
    <tx:annotation-driven/>

    <!-- DataSource JNDI -->
    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/paidos" resource-ref="true" />

    <!--  Session factory -->
    <beans:bean id="sessionFactory" 
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" 
        p:dataSource-ref="dataSource"
        p:hibernateProperties-ref="hibernateProperties"
        p:packagesToScan="com.carloscortina.paidosSimple.model" />

    <!--  Hibernate Properties -->
    <util:properties id="hibernateProperties">
        <beans:prop key="hibernate.dialect">
            org.hibernate.dialect.MySQL5InnoDBDialect
        </beans:prop>
        <beans:prop key="hibernate.show_sql">false</beans:prop>
    </util:properties>

    <beans:bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager"
        p:sessionFactory-ref="sessionFactory" />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <context:component-scan base-package="com.carloscortina.paidosSimple" />

</beans:beans>

我不知道缺少什么,所以欢迎任何想法,在此先感谢。

编辑:UsuarioDaoImp

package com.carloscortina.paidosSimple.dao;

import java.util.ArrayList;
import java.util.List;


import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.carloscortina.paidosSimple.model.Usuario;

@Repository
public class UsuarioDaoImp implements UsuarioDao {

    private static final Logger logger = LoggerFactory.getLogger(UsuarioDaoImp.class);

    @Autowired
    private SessionFactory sessionFactory;

    private Session getCurrentSession(){
        return sessionFactory.getCurrentSession();
    }

    @Override
    public Usuario getUsuario(String username) {
        logger.debug("probando");
        List<Usuario> userList = new ArrayList<Usuario>();
        Query query = getCurrentSession().createQuery("from Usuario u where u.Username = :username");
        query.setParameter("username", username);
        userList = query.list();
        if (userList.size() > 0){
            return (Usuario) userList.get(0);
        }else{
            return null;
        }
    }

}

尝试使用 UsuarioDaoImp 添加 bean 后,出现此错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'usuarioServicioImp': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.carloscortina.paidosSimple.dao.UsuarioDao com.carloscortina.paidosSimple.service.UsuarioServicioImp.usuarioDao; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.carloscortina.paidosSimple.dao.UsuarioDao] is defined: expected single matching bean but found 2: usuarioDaoImp,userDao

UsuarioServiceImp

package com.carloscortina.paidosSimple.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.carloscortina.paidosSimple.dao.UsuarioDao;
import com.carloscortina.paidosSimple.model.Usuario;

@Service
@Transactional
public class UsuarioServicioImp implements UsuarioService{

    @Autowired
    private UsuarioDao usuarioDao;

    @Override
    public Usuario getUsuario(String username) {
        return usuarioDao.getUsuario(username);
    }

}

我认为我对这个主题知之甚少,这就是为什么我要遵循一个例子但我以这个结尾,所以如果我没有正确提供信息或者我误解了概念,我深表歉意。

弹簧安全.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">


    <beans:bean class="com.carloscortina.paidosSimple.service.CustomUserDetailsService" id="customUserDetailsService"></beans:bean>

    <security:http auto-config="true">
        <security:intercept-url pattern="/sec/moderation.html" access="ROLE_ASISTENTE" />  
        <security:intercept-url pattern="/admin/*" access="ROLE_DOCTOR" />   
        <security:form-login login-page="/user-login.html" 
            default-target-url="/success-login.html" 
            authentication-failure-url="/error-login.html" />  
        <security:logout logout-success-url="/index.html" />
    </security:http>  

    <security:authentication-manager>  
        <security:authentication-provider user-service-ref="customUserDetailsService">  
            <security:password-encoder hash="plaintext" />
        </security:authentication-provider>  
    </security:authentication-manager>  

</beans:beans>  
4

2 回答 2

3

您如何访问 CustomUSerDetailsS​​ervice 类?我希望您没有在安全配置文件或任何其他 Spring 配置中将此类添加为 bean?

已编辑: 您的服务 bean 使用 @service 进行注释,并且您还在 xml 中声明了它,spring 创建了两个服务 bean,一个基于 @service 注释(完全填充为其自动写入),第二个使用 xml 配置(我假设您在其中没有显式注入 dao 依赖项),所以第二个没有 dao 对象集。当您使用在安全配置中声明的服务 bean 的 bean 名称时,您在调试时将 userDao 设为 null。

在安全 xml 中注释显式 bean 定义,直接使用 ref="customUSerDetailsS​​ervice" 因为 @service 注释已经在 spring 上下文中添加了一个具有此名称的 bean。

即在您的安全配置中评论/删除这一行,一切都应该工作。

<beans:bean class="com.carloscortina.paidosSimple.service.CustomUserDetailsService" id="customUserDetailsService"></beans:bean>

当您使用 @component/@service 注释 bean 时,spring 会添加一个名称等于短类名(第一个字母小写)的 bean,因此名称为“customUserDetailsS​​ervice”的 bean 已经存在,在 xml 中显式定义它会覆盖它。

或者在 xml config 中显式声明所有 bean 定义(包括依赖项)

于 2013-08-05T17:45:09.967 回答
1

将dao包添加到组件扫描中

<context:component-scan base-package="com.carloscortina.paidosSimple, com.carloscortina.paidosSimple.dao" />
于 2013-08-05T16:44:58.860 回答