You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by ryannelsonaz <mw...@hotmail.com> on 2011/08/02 18:49:47 UTC
Wiring a CredentialsMatcher into a Realm using Guice
I'm using the new shiro-guice integration module (available in the latest
Shiro snapshot), and had a problem marrying it with shiro.ini. I'd like to
specify user passwords using MD5-hashed values in the INI file, but for this
to work, I have to instruct the IniRealm to use that algorithm.
Because I'm wiring things together with Guice, we can't use the default
[main] section of the INI file. My first pass was to create two providers
in my Guice module and wire the MD5 CredentialsMatcher by hand as follows:
@Override
protected void configureShiroWeb() {
bindRealm().to( IniRealm.class );
}
@Provides
@Singleton
Ini loadShiroIni() {
return Ini.fromResourcePath( "classpath:shiro.ini" );
}
@Provides
@Singleton
IniRealm loadIniRealm( Ini ini ) {
IniRealm realm = new IniRealm( ini );
HashedCredentialsMatcher credentialsMatcher = new
HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName( new Md5Hash().getAlgorithmName()
);
realm.setCredentialsMatcher( credentialsMatcher );
return realm;
}
This works. It was suggested to me to bind a CredentialsMatcher rather than
using a Provider. As I tried to implement this though, I realized this
won't work since Guice requires an @Inject annotation on a constructor or a
setter method in order to inject a bound class. For classes whose source
you do not control, you must otherwise use a Provider (or bind
toConstructor(), but that's not relevant here).
Shiro, of course, doesn't have the @Inject annotation on
AuthenticatingRealm.setCredentialsMatcher(), so I think I must use a
Provider as I've done. Is there anything I'm missing? Is there a cleaner
(read: not hand-wired) approach to do this with Guice?
--
View this message in context: http://shiro-user.582556.n2.nabble.com/Wiring-a-CredentialsMatcher-into-a-Realm-using-Guice-tp6645572p6645572.html
Sent from the Shiro User mailing list archive at Nabble.com.
Re: Wiring a CredentialsMatcher into a Realm using Guice
Posted by ryannelsonaz <mw...@hotmail.com>.
Makes sense, and that did the trick. Thanks!
--
View this message in context: http://shiro-user.582556.n2.nabble.com/Wiring-a-CredentialsMatcher-into-a-Realm-using-Guice-tp6645572p6650651.html
Sent from the Shiro User mailing list archive at Nabble.com.
Re: Wiring a CredentialsMatcher into a Realm using Guice
Posted by Jared Bunting <ja...@peachjean.com>.
On 08/03/2011 02:49 PM, ryannelsonaz wrote:
> Jared,
>
> Hmm, we're close but not quite there. Here are the relevant lines from my
> module, as you specified:
>
> @Override
> protected void configureShiroWeb() {
> try {
> bindRealm().toConstructor( IniRealm.class.getConstructor( Ini.class ) );
> } catch ( NoSuchMethodException e ) {
> throw new RuntimeException( "Code Problem.", e );
> }
> bind( CredentialsMatcher.class ).to( HashedCredentialsMatcher.class );
add:
bind(HashedCredentialsMatcher.class);
> bindConstant().annotatedWith( Names.named( "shiro.hashAlgorithmName" )
> ).to(Md5Hash.ALGORITHM_NAME );
> }
>
> @Provides
> @Singleton
> Ini loadShiroIni() {
> return Ini.fromResourcePath( "classpath:shiro.ini" );
> }
>
> This results in an AuthenticationException. Tracing the execution, I can
> see the HashedCredentialsMatcher gets set as expected, but the algorithim
> never does. The property HashedCredentialsMatcher.hashAlgorithm is null.
>
> On a related side-note: I'm curious how you implemented the DI without using
> the @Inject annotation.
Well, I'm using a Guice TypeListener. When it encounters an class in
org.apache.shiro package, but NOT in org.apache.shiro.guice, it attempts
to inject it like a standard JavaBean (using setters, and introspecting
types).
It turns out that Guice TypeListeners are only run against types that
are explicitly bound - not just-in-time bindings. So, if you want
anything injected, you have to explicitly bind it.
I'll add that to the docs.
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Wiring-a-CredentialsMatcher-into-a-Realm-using-Guice-tp6645572p6649980.html
> Sent from the Shiro User mailing list archive at Nabble.com.
Re: Wiring a CredentialsMatcher into a Realm using Guice
Posted by ryannelsonaz <mw...@hotmail.com>.
Jared,
Hmm, we're close but not quite there. Here are the relevant lines from my
module, as you specified:
@Override
protected void configureShiroWeb() {
try {
bindRealm().toConstructor( IniRealm.class.getConstructor( Ini.class ) );
} catch ( NoSuchMethodException e ) {
throw new RuntimeException( "Code Problem.", e );
}
bind( CredentialsMatcher.class ).to( HashedCredentialsMatcher.class );
bindConstant().annotatedWith( Names.named( "shiro.hashAlgorithmName" )
).to(Md5Hash.ALGORITHM_NAME );
}
@Provides
@Singleton
Ini loadShiroIni() {
return Ini.fromResourcePath( "classpath:shiro.ini" );
}
This results in an AuthenticationException. Tracing the execution, I can
see the HashedCredentialsMatcher gets set as expected, but the algorithim
never does. The property HashedCredentialsMatcher.hashAlgorithm is null.
On a related side-note: I'm curious how you implemented the DI without using
the @Inject annotation.
--
View this message in context: http://shiro-user.582556.n2.nabble.com/Wiring-a-CredentialsMatcher-into-a-Realm-using-Guice-tp6645572p6649980.html
Sent from the Shiro User mailing list archive at Nabble.com.
Re: Wiring a CredentialsMatcher into a Realm using Guice
Posted by Jared Bunting <ja...@peachjean.com>.
The shiro-guice integration module should inject setters on shiro classes
(those in org.apache.shiro package or subpackages) even without the @Inject
annotation. I'll try to make that clearer on the wiki page. If it doesn't
work, that's a bug.
As for the hash algorithm name, have a look at the "Properties" section of
the guice page.
I think what you need to do is:
bind(CredentialsMatcher.class).to(HashedCredentialsMatcher.class);
bindConstant().annotatedWith(Names.named("shiro.hashAlgorithmName")).to(Md5Hash.ALGORITHM_NAME);
Let me know if that helps.
On Aug 2, 2011 12:50 PM, "ryannelsonaz" <mw...@hotmail.com> wrote:
I'm using the new shiro-guice integration module (available in the latest
Shiro snapshot), and had a problem marrying it with shiro.ini. I'd like to
specify user passwords using MD5-hashed values in the INI file, but for this
to work, I have to instruct the IniRealm to use that algorithm.
Because I'm wiring things together with Guice, we can't use the default
[main] section of the INI file. My first pass was to create two providers
in my Guice module and wire the MD5 CredentialsMatcher by hand as follows:
@Override
protected void configureShiroWeb() {
bindRealm().to( IniRealm.class );
}
@Provides
@Singleton
Ini loadShiroIni() {
return Ini.fromResourcePath( "classpath:shiro.ini" );
}
@Provides
@Singleton
IniRealm loadIniRealm( Ini ini ) {
IniRealm realm = new IniRealm( ini );
HashedCredentialsMatcher credentialsMatcher = new
HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName( new
Md5Hash().getAlgorithmName()
);
realm.setCredentialsMatcher( credentialsMatcher );
return realm;
}
This works. It was suggested to me to bind a CredentialsMatcher rather than
using a Provider. As I tried to implement this though, I realized this
won't work since Guice requires an @Inject annotation on a constructor or a
setter method in order to inject a bound class. For classes whose source
you do not control, you must otherwise use a Provider (or bind
toConstructor(), but that's not relevant here).
Shiro, of course, doesn't have the @Inject annotation on
AuthenticatingRealm.setCredentialsMatcher(), so I think I must use a
Provider as I've done. Is there anything I'm missing? Is there a cleaner
(read: not hand-wired) approach to do this with Guice?
--
View this message in context:
http://shiro-user.582556.n2.nabble.com/Wiring-a-CredentialsMatcher-into-a-Realm-using-Guice-tp6645572p6645572.html
Sent from the Shiro User mailing list archive at Nabble.com.