I'm using Spring MVC, Tiles and Shiro.
This is how my unauthorizedUrl property is configured:
<property name="unauthorizedUrl" value="/unauthorized"/>
My expectation is that when MyAuthorizingRealm
finds invalid credentials, that Shiro will redirect to /unauthorized
.
But, that doesn't happen for me on form submission. I have a login @Controller
that is mapped to handle GET and POST actions for /login
. For accesses to the url /lists
the login form is displayed. So it seems to work in one case but not the other.
@Controller
@RequestMapping(value = "/login")
public class LoginController {
@RequestMapping(method = RequestMethod.GET)
public String getLoginFormView(Model model) {
return "login";
}
// if this method doesn't exist a Post not supported exception is thrown
@RequestMapping(method = RequestMethod.POST)
public String handlePost() {
return "this view doesn't exist";
}
}
Even if I throw AuthenticationException
from MyAuthorizingRealm.doGetAuthenticationInfo()
I still can't get Shiro to redirect to /unauthorized
. It always ends up continuing with the filter chain and executes the POST method in the @Controller
; and of course I expect a redirect instead.
Here is my webapp-context.xml
:
http://pastebin.com/XZaCKqEC
And here is my web.xml
:
http://pastebin.com/5H81Tm8A
Following is some TRACE log output from Shiro. Shiro works when you try to access /lists
. But, when the login form is submitted the redirect to /unauthorized
never happens. Note, the login submission is detected:
http://pastebin.com/ZEK3CTdJ
So, the login submission is detected but the original filter chain is executed anyway instead of redirecting to /unauthorized
I'm stumped. Many thanks for any help and if you need more info please let me know.
I think I see two problems:
1) Your pastebin for your spring xml does not show the SecurityManager being configured with your realm. I.e. it needs to look like this:
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
2) You're setting up a Spring MVC controller to perform authentication, which implies you want to control when subject.login
is called and not rely on Shiro's built-in FormAuthenticationFilter (authc
).
If you do this, you will need to redefine the authc
filter to be a
PassThruAuthenticationFilter.
This allows the request to 'pass through' the filter chain to your Login view/controller where you are responsible for calling subject.login
You can do that in your spring.xml by setting the filters
property and using authc
as the name for your configured filter:
<bean id="passthruAuthcFilter" class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter">
<property name="loginUrl" value="/login"/>
</bean>
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
...
<property name="filters">
<util:map>
<entry key="authc" value-ref="passthruAuthcFilter"/>
</util:map>
</property>
...
</bean>
Also, as a tip, you might want to use Shiro's WebUtils to redirect the end-user to the url they originally attempted before being redirected to login. Shiro's FormAuthenticationFilter
does this automatically, but when you perform the login yourself, you're responsible for doing this redirect if it is desired.
For example, in your LoginController
's handlePost method:
subject.login(authcToken);
WebUtils.redirectToSavedRequest(request, response, yourFallbackUrlIfThereIsntASavedRequest);
return null; //tells Spring MVC you've handled the response, and not to render a view
来源:https://stackoverflow.com/questions/10303464/shiro-doesnt-redirect-to-unauthorizedurl-w-invalid-login-shiro-with-spring-an