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.