开发者

How to configure Shiro + Spring MVC when @Controller REDIRECTS to a login page

I have a typical Spring MVC + GWT architecture with Apache Shiro as a security layer.

Problem: No matter what protocol is used for a request to the App server, pages should be returned in the protocol specified in the request's "X-Forwarded-Proto" header (so, app server can receive a HTTP request, but if the header says HTTPS, it should respond using HTTPS). Obviously, the configuration specified in the Shiro-Spring tutorial won't work as it has nothing to do with the protocols (login.jsp will be returned using the protocol used in request):

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  <property name="securityManager" ref="securityManager"/>
  <property name="loginUrl" value="/login.jsp"/>
  <p开发者_开发技巧roperty name="filterChainDefinitions">
    <value>
        /** = authc
    </value>
  </property>
</bean>

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

<bean id="myRealm" class="com.myapp.security.DBRealm">
   <property name="credentialsMatcher" ref="sha256Matcher"/>
</bean>

Possible solution:

Use @Controller to REDIRECT to the login view with the specified protocol:

@RequestMapping(value="/login", method=RequestMethod.GET)
public RedirectView doLogin(HttpServletRequest req) throws MalformedURLException {
  URL originalURL = new URL(req.getRequestURL().toString());
  return new RedirectView(new URL(req.getHeader("X-Forwarded-Proto"), originalURL.getHost(), "/login.jsp").toString());
}

and change the loginUrl in shiro configuration to point to /login, so that @controller catches it:

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  <property name="securityManager" ref="securityManager"/>
  <property name="loginUrl" value="/login"/>
  ... leave everything else the same
</bean>

But with this configuration, although I get the same login page, the myRealm (com.myapp.security.DBRealm) is not triggered at all (meaning, the credentials are not checked), and login always fails. Seems like the redirected page loses the "hook" to the realm.

Any ideas on what I am doing wrong?


The reason this is failing is because the Shiro authc Filter (a FormAuthenticationFilter) expects the loginUrl to be the one where the login attempt occurs.

That is, when authc filters a request that matches the loginUrl, it will automatically support form-based authentication. Because you are redirecting the end-user to a URL that does not match the loginUrl (i.e. loginUrl=/login, but you redirect them to /login.jsp), the authc filter won't perform a login.

Your best option IMO:

Subclass FormAuthenticationFilter and override the redirectToLogin method to use your X-Forwarded-Proto logic. Then redefine 'authc' to be your custom subclass. For example, using shiro .ini:

    [main]
    ...
    authc = com.foo.my.FormAuthenticationFilterSubclass

Also, if you want this behavior in Shiro directly (so Shiro looks for that header when performing a redirect by default) so you can remove your subclass, please open a feature request in Apache Shiro's Jira.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜