2

我使用 Spring MVC、Spring Security 和 Apache Tiles,但遇到以下问题:

我希望未经身份验证的用户登陆我网站的主页 URL(即www.mywebsite.com/),登录表单将显示给他们,以便他们可以从那里进行身份验证。

然后,一旦用户通过身份验证,我希望在网站的主页 URL 上向他们显示完全不同的页面内容www.mywebsite.com/(仍然)可能使用另一个模板/jsp。

我想要实现的基本上是能够根据用户是否经过身份验证为同一个 URL 显示不同的内容——所有这些都使用 Spring 安全性和 Spring MVC。

我研究了 Spring Security,但无法找到上述问题的解决方案。其他人也遇到过类似的问题(请参阅:Spring security-same page to deliver different content based on user role

任何人都可以就如何实现这一点提供指示或建议吗?

4

5 回答 5

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");
        }
    }

}
于 2012-09-26T11:41:39.027 回答
2

Spring 论坛的成员为我提供了一个不错的优雅解决方案。这里是:

@RequestMapping("/")
@PreAuthorize("isAuthenticated()")
public String authenticatedHomePage() {
    return "authenticatedHomePage";
}

@RequestMapping("/")
public String homePage() {
    return "homePage";
}

它非常好,因为它依赖于 Spring Security。见这里(博客文章

于 2012-09-26T17:08:13.193 回答
1

我可以想出几种方法来实现你想要的。

首先,您可以使用 Spring Security taglib 有条件地在您的视图模板中呈现内容,具体取决于用户是否经过正确的身份验证。有关 Spring Security taglib 的更多信息在这里。粗略地说,这会使您的视图模板看起来像:

if(user is authenticated)
     render content for authenticated user
else
     render log-in form

然而,这感觉有点生硬,因为无论您的用户是否经过正确身份验证,您的控制器都会始终创建模型。每当您想显示登录表单时,您还需要在视图模板中使用此逻辑。

另一种方法是创建一个HandlerInterceptor实现,它将所有请求转发到负责呈现登录页面的控制器,直到用户完全通过身份验证。您可以使用 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。这避免了您必须在所有控制器之间复制逻辑并且易于测试。

于 2013-06-25T17:10:10.860 回答
0

你可以尝试使用

<security:authorize access=”isAnonymous()”&gt;
not authenticated page
</security:authorize>
<security:authorize access=”isAuthenticated()”&gt;
authenticated page
</security:authorize>

或者您可以在控制器中返回“redirect: page_for_not_auth”作为视图名称,以将响应重定向到另一个控制器/方法,该控制器/方法处理未经过身份验证的请求。

于 2012-09-26T12:55:44.977 回答
0

你应该这样做:

@RequestMapping("/")
public String generalHomePage() {
    ...
}

@RequestMapping("/")
@PreAuthorize("isAuthenticated()")
public String secureHomePage() {
    ...
}
于 2018-05-25T13:13:36.373 回答