3

I am trying to gather the necessary information to be successful with my objective. My goal is simple, take a advantage of Shiro for authentication and authorization. I wish to deploy shiro in a Java Web Application context. I want users to be able to login and check credentials against a MySQL database. I want to implement the SHA256 hashing for passwords. I am not fancy so I use traditional JSPs and Servlets.

Technologies I am using: Apache Tomcat 7, Apache Shiro, MySQL, Apache Web Server

Am I on the right track here?


/WEB-INF/shiro.ini

[main]
# Using my JNDI resource for JDBC
dataSource = org.apache.shiro.jndi.JndiObjectFactory
dataSource.resourceName = jdbc/myResource
dataSource.resourceRef = true
jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource = $dataSource

# Using Pass Thru security filter so I can manage login.
authc = org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter
authc.loginUrl = /login
authc.successUrl = /my-account

# Use default service and password matcher
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
passwordMatcher.passwordService = $passwordService

#Realms section
# Finally, set the matcher on a realm that requires password matching for account authentication: 
# myRealm.credentialsMatcher = $passwordMatcher 
# ???

[users]

[roles]


[urls]
/login = authc
/logout = logout

Question 1: Under my "# Use default service and password matcher" section, is this proper way to configure Shiro to perform password comparisons with SHA256?

Question 2: Under my "# Realms section" section, I don't understand what to do here. Can you please suggest what the CredentialsMatcher code should look like?

In regards to question 2, I noticed on the CredentialsMatcher interface docs, its suggested using the HashedCrendentialsMatcher to perform comparisons. Am I supposed to create a new java class that uses the HashedCredentialsMatcher? Then I would reference that class as my "realm" in the shiro.ini file?


New Account Signup

When creating a new user I want to encrypt the password. I am choosing to use the encryption tools provided by the Shiro framework. I will use a DefaultPasswordService object instance to encrypt my users password. The resulting value is stored in the database.

String rawPassword = "secret";
DefaultPasswordService passwordService = new DefaultPasswordService();
String encryptedPassword = passwordService.encryptPassword(rawPassword);
String hash = passwordService.hashPassword(rawPassword).toString();

//Create the user
User user = new User();
user.setUsername(username)
user.setEncryptedPassword(encryptedPassword);
user.setHash(hash);

//Save to Database
userDAO.save(user);

//Log the user in immediately after new account created.
try {
    UsernamePasswordToken userToken = new UsernamePasswordToken(username, rawPassword);
    SecurityUtils.getSubject().login(userToken);
} catch (UnknownAccountException uae) {
    LogMe.s(this.getClass().getName(), "Log error specific message here...", uae);
} catch (IncorrectCredentialsException ice) {
    LogMe.s(this.getClass().getName(), "Log error specific message here...", ice);
} catch (LockedAccountException lae) {
    LogMe.s(this.getClass().getName(), "Log error specific message here...", lae);
} catch (ExcessiveAttemptsException eae) {
    LogMe.s(this.getClass().getName(), "Log error specific message here...", eae);
} catch (AuthenticationException ae) {
    LogMe.s(this.getClass().getName(), "Log error specific message here...", ae);
}catch (Exception ex) {
    LogMe.s(this.getClass().getName(), "Log error specific message here...", ex);
}

Question 3: As far as my "New Account Signup" logic goes, is this an acceptable approach? Suggestions? Asked another way, am i configuring this correctly?

Question 4: When storing the hash value in MySQL, do I convert it to a String using hashPassword()? Is there a recommended length for the hash value field: e.g. varchar(15)?


User Login

I have chosen to manually authenticate users in the login process. I am able to retrieve the username/password from the POST from the Servlet. I will eventually set up AJAX login mechanism which is why I choose this approach. This is an area where I am stumped. Below are two snippets. The first is the html form to submit to my servlet. The second snippet is a method that performs the authentication.

/login

<form name="loginform" action="login.do" method="post">
    <p>Username</p> 
    <input type="text" name="username" />
    <p>Password</p>        
    <input type="password" name="password" />
    <input type="submit" value="Login" />
</form>

The login method

//Getters and Setters omitted for username, rawPassword.

private void login() {
    if (!SecurityUtils.getSubject().isAuthenticated()) {
        String fallbackUrl = "/user-account-default-page";
        try {
            UsernamePasswordToken userToken = new UsernamePasswordToken(username, rawPassword);
            SecurityUtils.getSubject().login(userToken);

            //Take advantage of the auto redirect to the page user wanted. Or default to the fallbackUrl
            WebUtils.redirectToSavedRequest(request, response, fallbackUrl);
        } catch (UnknownAccountException uae) {
            LogMe.s(this.getClass().getName(), "Log error specific message here...", uae);
        } catch (IncorrectCredentialsException ice) {
            LogMe.s(this.getClass().getName(), "Log error specific message here...", ice);
        } catch (LockedAccountException lae) {
            LogMe.s(this.getClass().getName(), "Log error specific message here...", lae);
        } catch (ExcessiveAttemptsException eae) {
            LogMe.s(this.getClass().getName(), "Log error specific message here...", eae);
        } catch (AuthenticationException ae) {
            LogMe.s(this.getClass().getName(), "Log error specific message here...", ae);
        }catch (Exception ex) {
            LogMe.s(this.getClass().getName(), "Log error specific message here...", ex);
        }
    }
}

/logout

Shiro logs out the user because of the snippet of code in the shiro.ini file? By setting the URL "/logout" equal to logout, Shrio logs user out. Is this correct?

# Section of the shiro.ini file
[urls]
/logout = logout

Thank you for any and all insights you might have. I hope that this question isn't overbearing and maybe helps others in the future. Also note, I originally asked this question on the shiro forums.

medokr
  • 441
  • 1
  • 5
  • 16

0 Answers0