Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using JDBCRealm to authenticate user with Shiro

I am trying to authenticate a servlet running within Tomcat 6 using Shiro.

I have the following shiro.ini file:

[main]
ps = org.apache.shiro.authc.credential.DefaultPasswordService
pm = org.apache.shiro.authc.credential.PasswordMatcher
pm.passwordService = $ps

aa = org.apache.shiro.authc.credential.AllowAllCredentialsMatcher
sm = org.apache.shiro.authc.credential.SimpleCredentialsMatcher

jof = org.apache.shiro.jndi.JndiObjectFactory
jof.resourceName = jdbc/UserDB
jof.requiredType = javax.sql.DataSource
jof.resourceRef = true

realm = org.apache.shiro.realm.jdbc.JdbcRealm
realm.permissionsLookupEnabled = true
realm.credentialsMatcher = $pm
; Note factories are automatically invoked via getInstance(),
;   see org.apache.shiro.authc.config.ReflectionBuilder::resolveReference
realm.dataSource = $jof

securityManager.realms = $realm

[urls]
/rest/** = authcBasic
/prot/** = authcBasic

And the following in my database:

mysql> select * from users;
+----------+------------------+----------+----------------------------------------------+--------------------------+
| username | email            | verified | password                                     | password_salt            |
+----------+------------------+----------+----------------------------------------------+--------------------------+
| admin    | a.muys@********* |        1 | ojSiTecNwRF0MunGRvz3DRSgP7sMF9EAR77Ol/2IAY8= | eHp9XedrIUa5sECfOb+KOA== |
+----------+------------------+----------+----------------------------------------------+--------------------------+
1 row in set (0.00 sec)

If I use the SimpleCredentialsManager it authenticates fine against a plaintext password in the users table. Trying to use the PasswordMatcher has been extremely frustrating.

The password and password_salt were obtained via the shiro-tools Hasher utility.

When I try to authenticate against a basic HelloWorld servlet I use for testing (path=rest/hello, context=/ws), I get the following in the logs:

15:35:38.667 [http-8080-2] TRACE org.apache.shiro.util.ClassUtils - Unable to load clazz named [ojSiTecNwRF0MunGRvz3DRSgP7sMF9EAR77Ol/2IAY8=] from class loader [WebappClassLoader
  context: /ws
  delegate: false
  repositories:
    /WEB-INF/classes/
----------> Parent Classloader:
org.apache.catalina.loader.StandardClassLoader@79ddd026
]

(Full log at https://gist.github.com/recurse/5915693 )

It appears to be trying to load my hashed password as a classname. Is this a bug, or a configuration error on my part? If it is a bug, how can I work around it? If it is a configuration error, what am I missing?

like image 747
Recurse Avatar asked Jul 03 '13 05:07

Recurse


1 Answers

First, thanks for providing a lot of information for this question - it makes providing an answer a lot easier.

By looking at your sample database row list, it does not appear that you are storing the output that the PasswordService expects when performing a hashed password comparison. For example:

$ java -jar ~/.m2/repository/org/apache/shiro/tools/shiro-tools-hasher/1.2.2/shiro-tools-hasher-1.2.2-cli.jar -p
Password to hash:
Password to hash (confirm):
$shiro1$SHA-256$500000$uxaA2ngfdxdXpvSWzpuFdg==$hOJZc+3+bFYYRgVn5wkbQL+m/FseeqDtoM5mOiwAR3E=

The String that starts with $shiro1$ is what you would save to the password column in the database. There is no need for a separate salt column as all the information Shiro needs is in the $shiro1$... String.

The DefaultPasswordService uses the same default configuration parameters (SHA-256, 500,000 iterations, etc) so if you use the Hasher CLI tool as I've shown above (no extra hash algorithm config), you don't need to customize the DefaultPasswordService POJO any further. However, if you change the hashing parameters on the CLI, you need to ensure that the same parameters are configured on the DefaultPasswordService bean (and/or its internal HashingService).

If you are still in testing and can change your DB schema, I'd recommend doing that now to have a single password field that stores the $shiro1$... string. Then you use the PasswordService as documented here under Usage:

http://shiro.apache.org/static/current/apidocs/org/apache/shiro/authc/credential/PasswordService.html

like image 197
Les Hazlewood Avatar answered Sep 28 '22 10:09

Les Hazlewood