Reputation: 1180
I have integrated Apache Shiro with Spring Boot with Spring Data JPA. The Spring Boot project is in this GitHub repo.
The problem is when I run and try to authenticate the app I get the following error
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).
It completely fails to authenticate, I managed to create this repo to elaborate my problem. Check it out.
Solutions and criticism are highly acceptable.
If any extra info is needed to clarify my question, just ask
Upvotes: 2
Views: 374
Reputation: 5369
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!");
}
}
}
Upvotes: 1