Yunus Einsteinium
Yunus Einsteinium

Reputation: 1180

Shiro with Springboot integration

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.

Update

If any extra info is needed to clarify my question, just ask

Upvotes: 2

Views: 374

Answers (1)

Miloš Milivojević
Miloš Milivojević

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

Related Questions