我已将Apache Shiro与Spring Boot与Spring Data JPA集成在一起。 Spring Boot项目位于this GitHub repo。
问题是当我运行并尝试验证应用程序时出现以下错误
roleAdmin.getId() 1: null
roleAdmin.getId() 2: 3
Current user is not authenticated.
2016-08-13 09:49:45.715 WARN 10528 --- [lication Thread] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: S0022
2016-08-13 09:49:45.716 ERROR 10528 --- [lication Thread] o.h.engine.jdbc.spi.SqlExceptionHelper : Column 'id' not found.
Authentication failed for token submission [org.apache.shiro.authc.UsernamePasswordToken - yunus, rememberMe=false]. Possible unexpected error? (Typical or expected login exceptions should extend from AuthenticationException).
它完全无法进行身份验证,我设法创建了this repo以详细说明我的问题。看看吧。
解决方案和批评是高度可以接受的。
如果需要任何额外信息来澄清我的问题,请询问
答案 0 :(得分:1)
Your error message is indicative of the problem, which lies in your User repository's @Query
definition:
@Query(value = "SELECT u.username FROM users u WHERE u.username = ?1", nativeQuery = true)
User findByUsername(String username);
As you can see, you're selecting only the username, instead of selecting every column. Since you're using Spring Data JPA, you don't really need the @Query
at all, it's enough to just say:
User findByUsername(String username);
Your other problem, however, is how you compare the passwords in your custom realm. The password coming from the DB will be encrypted, meaning that you cannot just say
user.getPassword().equals(new String(upat.getPassword()))
You'll have to compare the passwords using the DefaultPasswordService
by calling its passwordsMatch
method and, since you'e just verified the paswords yourself, you should use AllowAllCredentialsMatcher
in your realm:
public class CustomSecurityRealm extends AuthorizingRealm {
@Autowired
private UserManagerService userManager;
@Autowired
private DefaultPasswordService passwordService;
public CustomSecurityRealm() {
this(new AllowAllCredentialsMatcher());
}
public CustomSecurityRealm(final CredentialsMatcher matcher) {
super(matcher);
}
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// remains the same
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken upat = (UsernamePasswordToken) token;
User user = userManager.findByUsername(upat.getUsername());
if(user != null && passwordService.passwordsMatch(upat.getPassword(), user.getPassword())) {
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
else {
throw new AuthenticationException("Invalid username/password combination!");
}
}
}