Search code examples
javaspringsecurityshirorealm

authc filter is not calling MyRealm in shiro with spring


I'm working on project with spring/hibernate/jax-rs(jersey). I wanted to integrate shiro to my project. I did configurations as in documentation. I have my own implementation of Realm.

Q: Problem is when authBasic path is called, it works fine with MyRealm. But when i call for authc(FormAuthenticationFilter) it shows login page and when I enter credentials it goes to login page again and no call to MyRealm.

I had project with same technologies except spring(no spring) before and I used same MyRealm. it worked fine.

Here is my code: web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
 version="2.4">

 <display-name>Restful Web Application</display-name>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-context.xml</param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
    </listener>

     <!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>


    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>
            org.glassfish.jersey.servlet.ServletContainer
        </servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>kg.enesaitech.barbulak.ws</param-value>            
        </init-param>       
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

</web-app>

spring-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"

    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:annotation-config/>
    <context:component-scan base-package="kg.enesaitech.barbulak.*" />



    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="/login.html"/>
        <property name="successUrl" value="/apps/warehause_manager"/>
        <property name="filterChainDefinitions">
            <value>
                /logout = logout
                /apps/admin/** = authcBasic
                /apps/accountant/** = authc
                /apps/production_manager/** = authc, roles[admin]
            </value>
        </property>
    </bean>

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="myRealm"/>
    </bean>
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <bean id="myRealm" class="kg.enesaitech.barbulak.security.MyRealm"></bean>  




    <bean name="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
             <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="barbulak" />
    </bean>
    <bean id="mapper" class="org.dozer.DozerBeanMapper" lazy-init="false">
        <property name="customFieldMapper" ref="dozerCustomFieldMapper" />

    <bean id="dozerCustomFieldMapper" class="kg.enesaitech.barbulak.providers.MyCustomFieldMapper" />

    <tx:annotation-driven/>




</beans>

MyRealm.java if it helps

package kg.enesaitech.barbulak.security;



public class MyRealm extends AuthorizingRealm {

    UsersHome usersHome = new UsersHome();
    RoleHome roleHome = new RoleHome();

    protected boolean permissionsLookupEnabled = false;

    public MyRealm() {
        super();
    }


    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
                throws org.apache.shiro.authc.AuthenticationException {

        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();

        AuthenticationInfo info = null;
        Users user = usersHome.getByUserName(username);

        if(user == null || user.getUserPass() == null){
            throw new UnknownAccountException("No account found for user [" + username + "]");
        }
        info = new SimpleAuthenticationInfo(username, user.getUserPass().toCharArray(), getName());

        return info;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        }

        String username = (String) getAvailablePrincipal(principals);
        System.out.println("Auth | username : " + username);


        Set<String> roleNames = roleHome.getNameSetByUserName(username);


        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleNames);
        return info;
    }

}

Any suggestions will be appreciated.

Note: I tried using shiro.ini configuration but it doesn't worked too. roles filter doesn't call MyRealm too. Only authcBasic is working right(calling Realm).


Solution

  • My problem was to add /login.html = authc to url, for others like me who searched for this one line for 3 days.