自动装配类

时间:2015-05-15 15:38:06

标签: java spring nullpointerexception autowired shiro

我正在使用Spring Boot和Shiro构建REST API以进行身份​​验证。当我尝试在我的领域代码中自动装配存储库时,我得到一个NullPointerException。在其他地方自动装配存储库不会产生此错误。

这是我的授权领域:

@Component
public class CCDAuthorizingRealm extends AuthorizingRealm {

    @Autowired
    private UserRepository userRepository;

    public CCDAuthorizingRealm() { }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        AuthenticationInfo authenticationInfo = null;
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        User user = null;
        try {
            user = userRepository.findByUsername(username);
        } catch (Exception e) {
            e.printStackTrace(System.err);
        }

        if (user != null) {
            authenticationInfo = new SimpleAuthenticationInfo(
                    new SimplePrincipalCollection(username, username),
                    user.getPassword());
        }

        return authenticationInfo;
    }
    ....
}

当我尝试调用findByUsername()方法时发生异常。

以下是我正在注入的存储库的代码。

@Transactional(readOnly=true)
@RepositoryRestResource(collectionResourceRel="users", path="users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
    User findByUsername(@Param("user") String user);
    ....
}

为了测试,我将存储库自动装入我的Application类并打印结果,我没有错误。为了完整起见,以下代码显示:

@SpringBootApplication
public class Application implements CommandLineRunner {
    @Autowired
    public UserRepository userRepository;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... strings) {
        System.out.println("\nServer up\n");
        User user = userRepository.findOne(new Long(1));
        System.out.println(user.getUsername());
    }
}

非常感谢任何帮助。

修改

据我所知,这个问题并不重复,而另一个问题的答案并不能解决我的问题。我正在注入bean并通知组件的IoC容器,但自动装配仍会产生NPE。

使用范围没有帮助,因为我只需要单个服务对象。 Configurable标签不是必需的,因为我是自动装配的,不需要创建新对象。

更新

这是我打电话给CCDAuthorizingRealm的地方。我是使用Shiro的新手,但我很确定这是正确的。

@RestController
@RequestMapping(produces="application/json")
public class AuthenticationController {

    CCDAuthorizingRealm realm = new CCDAuthorizingRealm();

    SecurityManager sm = new DefaultSecurityManager(realm);

    public AuthenticationController() { }

    /**
     * Authenticate user with supplied credentials
     *
     * @param login - credentials
     * @return success or failure message
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST, consumes="application/json")
    public String login(@RequestBody LoginInfo login) {
        String response;
        UsernamePasswordToken token = new UsernamePasswordToken(
                    login.getUsername(),
                    login.getPassword(),
                    false);
        try {
            SecurityUtils.setSecurityManager(sm);
            Subject currentUser = SecurityUtils.getSubject();
            if (currentUser.isAuthenticated()) {
                currentUser.logout();
            }
            currentUser.login(token);
            response = token.toString();
        } catch (AuthenticationException e) {
            response = "Error: Incorrect username or password";
        }

        return response;
    }
}

我目前正尝试在控制器中创建我的领域的新实例。我这样做是因为当我尝试:

@Autowired
CCDAuthorizingRealm realm;
SecurityManager sm = new DefaultSecurityManager(realm);

初始化安全管理器时会出现运行时错误,因为它会抱怨域为空。但是,我不明白为什么领域是空的,因为它被注释为一个组件。也许这是我问题的根源。

1 个答案:

答案 0 :(得分:1)

我发现了问题的答案。这是我在applicationContext.xml中的内容:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager" />
    <property name="loginUrl" value="/login" />
    <property name="successUrl" value="/home" />
    <property name="unauthorizedUrl" value="/login" />
    <property name="filterChainDefinitions">
        <value>
            /login = authc
        </value>
    </property>
</bean>

此配置的问题是正在过滤掉登录URL。解决方法是简单地将值更改为home,如下所示:

<value>
    /home = authc
</value>

相反,我认为将主页设置在过滤器后面。