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.