我使用Spring MVC,Spring Security和Apache Tiles,我有以下问题:
我希望未经身份验证的用户登陆我网站的主页网址(即www.mywebsite.com/
),其中会向他们显示一个登录表单,以便他们可以从那里验证。
然后,一旦用户通过身份验证,我希望在网站的主页网址(仍为www.mywebsite.com/
)上显示完全不同的页面内容,可能使用其他模板/ JSP。
我想要实现的基本上是能够根据用户是否经过身份验证来显示相同URL的不同内容 - 所有这些都使用Spring安全性和Spring MVC。
我研究过Spring Security,但无法找到上述问题的解决方案。其他人遇到了类似的问题(参见:Spring security - same page to deliver different content based on user role)
任何人都可以提供有关如何实现这一点的指示或建议吗?
答案 0 :(得分:3)
我能想到的一个解决方案是从请求中检入MVC控制器中的用户主体,如果已经过身份验证/有角色返回一个ModelAndView,否则返回另一个:
@Controller
public class MyController{
public ModelAndView doSomething(HttpServletRequest request, HttpServletResponse response){
if(request.getUserPrincipal() != null && request.isUserInRole("someRole"){
return new ModelAndView("view1");
}
else {
return new ModelAndView("view2");
}
}
}
答案 1 :(得分:2)
Spring论坛的成员为我提供了一个漂亮而优雅的解决方案。这是:
@RequestMapping("/")
@PreAuthorize("isAuthenticated()")
public String authenticatedHomePage() {
return "authenticatedHomePage";
}
@RequestMapping("/")
public String homePage() {
return "homePage";
}
这很好,因为它依赖于Spring Security。见这里(blog post)
答案 2 :(得分:1)
我可以想到几种实现你想要的方法。
首先,您可以使用Spring Security标记库有条件地呈现View模板中的内容,具体取决于用户是否经过了正确的身份验证。有关Spring Security标记库的更多信息是here。粗略地说,这将使您的View模板看起来像:
if(user is authenticated)
render content for authenticated user
else
render log-in form
然而,感觉有点生硬,因为无论用户是否经过正确的身份验证,您的控制器始终都会创建模型。每当您想要显示登录表单时,您还需要在View模板中使用此逻辑。
另一种方法是创建一个HandlerInterceptor实现,将所有请求转发给负责呈现登录页面的Controller,直到用户完全通过身份验证。您可以使用HandlerInterceptor的preHandle()方法执行此操作:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class MyHandlerInterceptor implements HandlerInterceptor
{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
{
SecurityContext sc = SecurityContextHolder.getContext();
boolean userAuthenticated = true;
/* Some logic in here to determine if the user is correctly authenticated */
if(!userAuthenticated)
{
request.getRequestDispatcher("/login").forward(request, response);
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception
{
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
{
}}
然后,您可以配置Spring MVC以将HandlerInterceptor实现映射到您需要此功能的URL。这样可以避免在所有控制器上复制逻辑,并且很容易测试。
答案 3 :(得分:0)
你可以尝试使用
<security:authorize access=”isAnonymous()”>
not authenticated page
</security:authorize>
<security:authorize access=”isAuthenticated()”>
authenticated page
</security:authorize>
或者您可以在控制器中返回“redirect:page_for_not_auth”作为视图名称,以将响应重定向到另一个处理未经验证的请求的控制器/方法。
答案 4 :(得分:0)
你应该这样做:
@RequestMapping("/")
public String generalHomePage() {
...
}
@RequestMapping("/")
@PreAuthorize("isAuthenticated()")
public String secureHomePage() {
...
}