liukaihandsome 2011-03-21 14:34
浏览 758
已采纳

spring3MVC +spring security3 关于扩展UserDetailsService 无法注入service的疑问.

问题描述:
我想用的spring3MVC+spring security3 实现登录权限的扩展.即扩展UserDetailsService 以达到从持久层上控制登录信息.
但是现在的问题是我启动服务器后,登录时在UserDetailsService 中 service层的方法无法注入.
如下图
[img]http://dl.iteye.com/upload/attachment/441866/0e084199-5973-3d55-a691-b8e1de9559ff.png[/img]
注意图中红线的地方. accountService为null.表示注入失败.

所以我想请教下大家:为什么会出现accountService为null 的问题.

我把主要的代码贴出来并在最后提供例子的下载.

首先是项目文件结构.

[img]http://dl.iteye.com/upload/attachment/441868/e7f16960-ef9f-3f2a-9491-9602bac6bfbe.png[/img]

[b]下面这段是继承UserDetailsService以实现持久层关联登录.[/b]

[code="java"]
@Transactional(readOnly = true)
public class UserDetailsServiceImpl implements UserDetailsService {

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

@Resource(name = "accountService")
private IAccountService accountService;

public UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException, DataAccessException {

    logger.info("username:" + username);

    User user = accountService.getUserInfo(username);

    if (user == null) {
        throw new UsernameNotFoundException("用户" + username + "不存在!");
    }

    Set<GrantedAuthority> grantedAuths = obtainGrantedAuthorities(user);

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

    UserDetails userDetails = new org.springframework.security.core.userdetails.User(
            username, user.getPassword(), enabled, accountNonExpired,
            credentialsNonExpired, accountNonLocked, grantedAuths);
    return userDetails;
}

private Set<GrantedAuthority> obtainGrantedAuthorities(User user) {

    Set<GrantedAuthority> authSet = Sets.newHashSet();

    for (Role role : user.getRoleList()) {
        for (Authority authority : role.getAuthorityList()) {
            logger.info("authority is :" + authority.getPrefixedName());
            authSet.add(new GrantedAuthorityImpl(authority
                    .getPrefixedName()));
        }
    }
    return authSet;

}

}[/code]

[b]service接口[/b]
[code="java"]public interface IAccountService {

/**
 * 根据用户登录名获得对应的权限信息.
 */
public User getUserInfo(String userName);

}[/code]
[b]
实现IAccountService的类[/b]

[code="java"]
@Service("accountService")
@Transactional
public class AccountService implements IAccountService {

@Resource(name="accountDao")
private IAccountDao dao;

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

public User getUserInfo(String userName) {

    // 根据登录名(userName)获得对应的信息
    User user = dao.getUserByloginName(userName);

    // 根据登录名获得对应的角色名.如 用户admin拥有"用户","管理员"这两个角色
    List<Role> roleList = dao.getRoleByUserName(userName);
    for (int i = 0; i < roleList.size(); i++) {

        // 根据角色的ID查询出每个角色对应的权限.
        List<Authority> authorityList = dao.getAuthorityByRoleId(roleList
                .get(i).getId());

        Role role = new Role();

        // 将查询出来的权限信息放入Role中的authorityList.
        role.setAuthorityList(authorityList);

        // 对象role放入集合中
        roleList.add(role);

    }

    // 将查询出来的角色信息(包含各个角色信息对应的权限信息)装入User里的roleList中.
    user.setRoleList(roleList);
    return user;
}

}[/code]

[b]IAccountDao接口[/b]
[code="java"]
public interface IAccountDao {

/**
 * 根据loginName获得对应用户信息
 * 
 * @return
 */
public User getUserByloginName(String loginName);

/**
 * 根据登录名获得对应的角色.
 * 
 * @param userName
 * @return
 */
public List<Role> getRoleByUserName(String userName);

/**
 * 根据角色ID获得对应的权限ID
 * 
 * @param roleId
 * @return
 */
public List<Authority> getAuthorityByRoleId(int roleId);

}[/code]

[b]实现IAccountDao接口的类
[/b]

[code="java"]

@Repository("accountDao")
public class AccountDao implements IAccountDao {

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

private SimpleJdbcTemplate jdbcTemplate;

@Resource(name = "dataSource")
public void setDataSource(DataSource dataSource) {
    this.jdbcTemplate = new SimpleJdbcTemplate(dataSource);
}

public User getUserByloginName(String loginName) {
    String sql = "SELECT id,email,login_name,name,password FROM acct_user WHERE login_name = ?";
    return jdbcTemplate.queryForObject(sql,
            new BeanPropertyRowMapper<User>(User.class),
            new Object[] { loginName });
}

public List<Role> getRoleByUserName(String userName) {
    String sql = "SELECT acct_role.id,acct_role.name FROM acct_user LEFT JOIN acct_user_role ON acct_user_role.user_id=acct_user.id  LEFT JOIN acct_role ON acct_role.id=acct_user_role.role_id  WHERE acct_user.login_name = ?";
    return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Role>(
            Role.class), new Object[] { userName });
}

public List<Authority> getAuthorityByRoleId(int roleId) {
    String sql = "SELECT acct_authority.id,acct_authority.name,acct_authority.url FROM acct_authority LEFT JOIN acct_role_authority ON acct_authority.id=acct_role_authority.authority_id LEFT JOIN acct_role ON acct_role.id=acct_role_authority.role_id WHERE acct_role.id= ?";
    return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Authority>(
            Authority.class), new Object[] { roleId });
}[/code]

然后是springsecurity3的配置文件

[code="java"]

<?xml version="1.0" encoding="UTF-8"?>
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd"
default-lazy-init="true">

<sec:http auto-config="true" use-expressions="true"
    access-denied-page="/denied">

    <sec:intercept-url pattern="/resources/**" filters="none" />

    <sec:intercept-url pattern="/" access="isAuthenticated()" />

    <sec:intercept-url pattern="/login" access="permitAll" />
    <!-- <sec:intercept-url pattern="/" access="hasRole('ROLE_ADMIN')" /> -->
    <sec:form-login login-page="/login"
        authentication-failure-url="/login?error=1" default-target-url="/" />

    <sec:logout invalidate-session="true" logout-success-url="/login"
        logout-url="/logout" />
</sec:http>

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

<bean id="customUserDetailsService" class="com.sjax.myapp.service.UserDetailsServiceImpl" />


[/code]

  • 写回答

9条回答 默认 最新

  • archy123 2011-03-22 10:00
    关注

    把[code="java"]
    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    [/code]
    放到 [code="java"]
    org.springframework.web.context.ContextLoaderListener
    [/code]
    前试试

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(8条)

报告相同问题?

悬赏问题

  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败
  • ¥15 MapReduce实现倒排索引失败
  • ¥15 ZABBIX6.0L连接数据库报错,如何解决?(操作系统-centos)
  • ¥15 找一位技术过硬的游戏pj程序员
  • ¥15 matlab生成电测深三层曲线模型代码