Recently was working with Shiro apache security library. Nice library with good inbuilt methods like “Remember Me” function.
You
just need to set the value at the time of login and it will take care
of rest. There is a small caveat, this functionality uses a hardcoded
AES key to encrypt the user name. More information here: http://shiro.apache.org/configuration.html#Configuration-ByteArrayValues
As the article rightly mentioned you can specify your own key in the shiro configuration ini file. Ok, I did the same but in my project we were using Spring to configure Shiro so instead of specifying the key in shiro.ini, I specified it in my properties file, which was read by the spring config file. Sample code: In spring config file:
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
<property name="subjectFactory" ref="mySubjectFactory"/>
<property name="rememberMeManager.cipherKey">
<value>Your Key</value>
</property>
</bean>
All worked fine, the key was picked up but my test cases started failing.
Downloaded
the source for Shiro, debugged the flow and found that Key picked
properly, also getting read in the AbstractRememberMeManager. After lots
of wasted hours, found that there was exception from a Java class while
encrypting user name. (invalid key length) . Come on I was using the
same code to generate the key as mentioned in the comments of default
cipher key.
(More wasted hours)
Finally
did something basic, provided the default shiro cipher key in the
properties file and again error. That made one thing clear – There was
some issue in how the key was read/set.
(why
I didn't find that while debugging, because the key is actually set as
byte array and me being proficient only in English and Hindi couldn't
notice the difference in byte representation :))
Ok,
now where is it getting corrupted. Downloaded the spring libs’ code and
found that the key received by the shiro class was getting corrupted in
the spring code itself. On further investigation found that instead of
using Base64.decode, spring was converting the key (which was encoded to
string with Base64) to bytes directly (but of-course).
Looks
like while reading from Shiro.ini file this is taken care of by shiro,
but when using spring, one needs to make sure that key is set in the
security manager after getting decoded to byte using Base64 only.
Huff, problem found, solution was much simpler. (no you cannot use spring's ByteArrayPropertyEditor it again does not use Base64)
Create a custom property editor.
1) Create a java class:
import java.beans.PropertyEditorSupport;
import com.ibm.xml.crypto.util.Base64;
public class BytesPropertyEditor extends PropertyEditorSupport {
public void setAsText(String text) throws IllegalArgumentException {
byte[] bytes = Base64.decode(text);
setValue(bytes);
}
}
2) Add following in your spring config:
<bean id="customEditorConfigure2"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="byte[]">
<bean class="com.amit.BytesPropertyEditor">
</bean>
</entry>
</map>
</property>
</bean>
And you are done. Happy remembering me... *_^
No comments:
Post a Comment