Search code examples
spring-mvcshiro

Returning a login error message using Shiro


Filters and redirects are not my strong point.

I have Shiro set up and working in Spring except that I'd like to return an error message on an invalid login while staying of the same page. So I'm causing a invalid login. I've got ShiroFilterFactoryBean set with a property that should send it to /ldapLoginErr which then I map to login.jsp and then process in a error function in my Controller. But I'm getting a 404 and the url is pointing to my base url instead /ldapLoginErr or /ldapLogin.

   class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

<mvc:view-controller path="/ldapLogin" view-name="ldapLogin" /> 
<mvc:view-controller path="/ldapLoginSuccess" view-name="ldapLogin" /> 
<mvc:view-controller path="/ldapLoginErr" view-name="ldapLogin" /> 


          <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <property name="loginUrl" value="/ldapLogin"/>
    <property name="unauthorizedUrl" value="/ldapLogin"/>
    <property name="successUrl" value="/ldapLogin"/>
    <property name="filterChainDefinitions">
        <value>
            [urls]
            /** = ssl[8443],authc, customAuthFilter
            [main]
            /logout = logout
        </value>
    </property>   
</bean>


      @RequestMapping(value = "/ldapLogin", method = RequestMethod.GET)
public ModelAndView login(Model model, HttpSession session){
    logger.debug("start login controller function");

    ModelAndView mav = new ModelAndView();
    return mav;  
}

@RequestMapping(value = "/ldapLoginErr", method = RequestMethod.GET)
public ModelAndView loginErr(Model model, HttpSession session){
        ModelAndView mav = new ModelAndView();
    mav.addObject("errorMessage", msgSrc.getMessage("auth.notauth", null, null, null));

    return mav;  
}

@RequestMapping(value = "/ldapLoginSuccess", method = RequestMethod.GET)
public ModelAndView loginSuccess(Model model, HttpSession session){

  }


  The following didn't work either:

      <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <property name="loginUrl" value="/ldapLogin"/>
    <property name="unauthorizedUrl" value="/ldapLoginErr"/>
    <property name="successUrl" value="/ldapLoginSuccess"/>

Thanks for any help


Solution

  • That seems convoluted.

    Create a controller that had a GET and POST endpoint mapped to /login

    GET returns the view for the login page.

    POST handles the call to shiro login.

    Authc filter

    <bean id="authc" class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter">
        <property name="loginUrl" value="/login"/>
    </bean>
    

    Filter chain def

    <property name="filterChainDefinitions">
      <value>
        /login = authc
        /logout = logout
        /secure/** = authc
      </value>
    </property>
    

    Controller

    @RequestMapping(method = RequestMethod.GET)
    public ModelAndView view() {
        return new ModelAndView(view);
    }
    
    @RequestMapping(method = RequestMethod.POST)
    public ModelAndView login(HttpServletRequest req, HttpServletResponse res, LoginForm loginForm) {
        try {
           Subject currentUser = SecurityUtils.getSubject();
           currentUser.login(new UsernamePasswordToken(loginForm.getUsername(), loginForm.getPassword());
           WebUtils.redirectToSavedRequest(req, res, fallBackUlr);
           return null; //redirect  
    
        } catch(AuthenticationException e) {
           ModelAndView mav = new ModelAndView(view)
           mav.addObject("errorMessage", "error");
           return mav;
        }
    }