【问题标题】:determine target url based on roles in spring security 3.1spring security 3.1中根据角色确定目标url
【发布时间】:2011-11-30 13:19:04
【问题描述】:
在 spring security 3.0 中,我们有 AuthenticationProcessingFilter 类,其中我们使用了 determineTargetUrl() 方法,它根据不同的角色返回 url。
现在,我们正在迁移到 spring security 3.1.0.RC3,我被困住了,我现在应该如何根据不同的角色确定 url,因为 AuthenticationProcessingFilter 类已从新版本中删除。谁能给我一些代码的简要步骤,以便我可以实现自定义过滤器以重定向到不同角色的不同页面。
【问题讨论】:
标签:
spring
spring-security
spring-3
【解决方案1】:
根据角色确定目标 url 的最佳方法是在 Spring Security 配置中指定目标 url,如下所示。这将适用于 Spring 3.0 或 3.1
<http>
...
<form-login login-page="/login" default-target-url="/default"/>
</http>
然后创建一个处理 default-target-url 的控制器。控制器应根据滚动重定向或转发。下面是一个使用 Spring MVC 的示例,但任何类型的控制器都可以工作(即 Struts、Servlet 等)。
@Controller
public class DefaultController {
@RequestMapping("/default")
public String defaultAfterLogin(HttpServletRequest request) {
if (request.isUserInRole("ROLE_ADMIN")) {
return "redirect:/users/sessions";
}
return "redirect:/messages/inbox";
}
}
这种方法的优点是它不耦合到任何特定的 Security 实现,它不耦合到任何特定的 MVC 实现,并且它很容易与 Spring Security 命名空间配置一起使用。一个完整的例子可以在我今年在 SpringOne 上展示的SecureMail 项目中找到。
另一种方法是您可以创建自定义AuthenticationSuccessHandler。该实现可能会扩展 SavedRequestAwareAuthenticationSuccessHandler,它是默认的 AuthenticationSuccessHandler。然后可以使用如下所示的命名空间进行连接。
<sec:http>
<sec:form-login authentication-success-handler-ref="authSuccessHandler"/>
</sec:http>
<bean:bean class="example.MyCustomAuthenticationSuccessHandler"/>
我不建议这样做,因为它与 Spring Security API 相关联,最好尽可能避免。
【解决方案2】:
使用自定义身份验证成功处理程序指定身份验证成功后基于用户角色的重定向。
您需要创建自定义身份验证成功处理程序,如下所示:
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
public class CustomeAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication) throws IOException {
handle(request, response, authentication);
}
protected void handle(HttpServletRequest request,
HttpServletResponse response, Authentication authentication)
throws IOException {
String targetUrl = determineTargetUrl(authentication);
if (response.isCommitted()) {
return;
}
redirectStrategy.sendRedirect(request, response, targetUrl);
}
protected String determineTargetUrl(Authentication authentication) {
boolean isTeacher = false;
boolean isAdmin = false;
Collection<? extends GrantedAuthority> authorities
= authentication.getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
if (grantedAuthority.getAuthority().equals("ROLE_USER")) {
isTeacher = true;
break;
} else if (grantedAuthority.getAuthority().equals("ROLE_ADMIN")) {
isAdmin = true;
break;
}
}
if (isTeacher) {
return "/user/account";
} else if (isAdmin) {
return "/admin/account";
} else {
throw new IllegalStateException();
}
}
public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
protected RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
}
然后修改spring security xml文件并定义你的bean并使用它
<bean id="customeAuthenticationSuccessHandler"
class="com.test.CustomeAuthenticationSuccessHandler"/>
<security:http auto-config="true" use-expressions="false">
<security:form-login login-page="/sign-in" login-processing-url="/sign-in" username-parameter="username"
password-parameter="password"
authentication-success-handler-ref="customeAuthenticationSuccessHandler"
always-use-default-target="true"
authentication-failure-url="/sign-in?error=true"/>
<security:logout logout-url="/logout" logout-success-url="/"/>
..
..
</security:http>