spring - How to use separate realms for authentication and authorization with Shiro and CAS? -
i'm working on web application multiple applications authenticates through cas sso server. howerver, each application should maintain respective roles , these roles stored in database specific application. so, need have 2 realms, 1 cas (for authc) , db (for authz).
this current shiro config. i'm getting redirection cas working properly, logged in user (subject) doesn't seems have roles/permission loaded in (e.g. securityutil.ispermitted() not working expected)
<bean id="jdbcrealm" class="org.apache.shiro.realm.jdbc.jdbcrealm"> <property name="name" value="jdbcrealm" /> <property name="datasource" ref="datasource" /> <property name="authenticationquery" value="select password system_user_accounts username=? , status=10" /> <property name="userrolesquery" value="select role_code system_roles r, system_user_accounts u, system_user_roles ur u.user_id=ur.user_id , r.role_id=ur.role_id , u.username=?" /> <property name="permissionsquery" value="select code system_roles r, system_permissions p, system_role_permission rp r.role_id=rp.role_id , p.permission_id=rp.permission_id , r.role_code=?" /> <property name="permissionslookupenabled" value="true"></property> <property name="cachingenabled" value="true" /> <property name="credentialsmatcher" ref="passwordmatcher" /> </bean> <!-- cas --> <bean id="casrealm" class="org.apache.shiro.cas.casrealm"> <property name="defaultroles" value="role_user" /> <property name="casserverurlprefix" value="http://localhost:7080/auth" /> <property name="casservice" value="http://localhost:8080/hawk-hck-web/shiro-cas" /> <property name="validationprotocol" value="saml" /> <property name="cachingenabled" value="true"></property> </bean> <bean id="cassubjectfactory" class="org.apache.shiro.cas.cassubjectfactory" /> <!-- security manager --> <bean id="securitymanager" class="org.apache.shiro.web.mgt.defaultwebsecuritymanager"> <property name="realms"> <list> <ref bean="casrealm" /> <ref bean="jdbcrealm" /> </list> </property> <property name="cachemanager" ref="cachemanager"/> <property name="subjectfactory" ref="cassubjectfactory" /> </bean> <bean id="casfilter" class="org.apache.shiro.cas.casfilter"> <property name="failureurl" value="/error"></property> </bean> <!-- shiro filter --> <bean id="shirofilter" class="org.apache.shiro.spring.web.shirofilterfactorybean"> <property name="securitymanager" ref="securitymanager" /> <property name="loginurl" value="http://localhost:7080/auth/login?service=http://localhost:8080/hawk-hck-web/shiro-cas" /> <property name="successurl" value="/home/index" /> <property name="unauthorizedurl" value="/error" /> <property name="filters"> <util:map> <entry key="casfilter" value-ref="casfilter" /> </util:map> </property> <property name="filterchaindefinitions"> <value> <!-- !!! order matters !!! --> /shiro-cas = casfilter /login = anon /logout = logout /error = anon /static/** = anon /** = authc </value> </property> </bean>
the way register realms securitymanager should in correct. can't find example of setup.
i have 2 questions here:
- what correct setup/configuration achieve above mentioned scenario?
- what best practice manage users , roles across different/seperate applications?
the problem running has fact both casrealm , jdbcrealm extends both authorizingrealm (authorizer) , authenticatingrealm. first step take jdbcrealm. jdbcrealm implementation inherits authenticatingrealm#supports(authenticationtoken token) method implementation. if extend jdbcrealm , override "supports" method return "false" token types jdbcrealm no longer used authentication purposes.
@override public boolean supports (authenticationtoken token) { return false; }
the casrealm different story, there no way (that know of) tell shiro not use realm implements authorizer when checking permissions. find frustrating default implementation protocols assumes both authorization , authentication needed. prefer each split 2 implementations (eg authenticatingcasrealm, authorizingcasrealm).
the logic behind checking permissions when multiple realms in use documented here. specific text references behavior is:
step 4: each configured realm checked see if implements same authorizer interface. if so, realm's own respective hasrole*, checkrole*, ispermitted*, or checkpermission* method called.
based on this, theoretically override each of named methods , of overloaded implementations return "false".
my solution problem based on prior comment splitting each realm 2 components, 1 authentication , 1 authorization. end more duplicate code way explicit in behaviors expecting implementation.
here's how go it:
create new class "authenticatingcasrealm" extends org.apache.shiro.realm.authenticatingrealm , implements org.apache.shiro.util.initializable.
copy , paste contents of existing casrealm source new "authenticatingcasrealm" class. (i aware taking copy-and-paste route of existing code frowned upon in described circumstsance know of no other way of solving problem.)
strip out methods implemented org.apache.shiro.realm.authorizingrealm.
update shrio configuration reference new authenticatingcasrealm implementation.
based on these changes should have 2 custom implementations in shrio config; 1 of jdbcrealm overriding "supports" method , 1 of casrealm removing authorization api methods.
there 1 additional method based on explicitly declaring authorizer via shiro's configuration may better suited situation.
here explicit declaration of authorizer , authenticator via custom shirofilter extension. both implemented , registered provided jndi names @ startup.
public class customshirofilter extends shirofilter { @override public void init () throws exception { super.init(); defaultwebsecuritymanager dwsm = (defaultwebsecuritymanager) getsecuritymanager(); dwsm.setauthorizer((authorizer)jndiutil.get("realms/authorizerrealm")); dwsm.setauthenticator((authenticator)jndiutil.get("realms/authenticatorrealm")); } }
Comments
Post a Comment