Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
根据用户是否经过身份验证,使用Spring安全性为同一URL显示不同的内容_Spring_Spring Mvc_Spring Security - Fatal编程技术网

根据用户是否经过身份验证,使用Spring安全性为同一URL显示不同的内容

根据用户是否经过身份验证,使用Spring安全性为同一URL显示不同的内容,spring,spring-mvc,spring-security,Spring,Spring Mvc,Spring Security,我使用Spring MVC、Spring Security和Apache Tiles,我有以下问题: 我希望未经身份验证的用户登录到我网站的主页URL(即www.mywebsite.com/),在那里向他们显示登录表单,以便他们可以从那里进行身份验证 然后,一旦用户通过身份验证,我希望完全不同的页面内容可以显示在网站的主URL上(仍然www.mywebsite.com/),可能使用另一个模板/jsp 我想要实现的基本目标是能够根据用户是否经过身份验证来显示同一URL的不同内容——所有这些都是使用

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

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

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

我想要实现的基本目标是能够根据用户是否经过身份验证来显示同一URL的不同内容——所有这些都是使用Spring security和Spring MVC实现的

我已经研究了Spring安全性,但未能找到上述问题的解决方案。其他人也遇到了类似的问题(见:)


任何人都可以提供关于如何实现这一点的指导或建议吗?

我能想到的一个解决方案是从请求中检查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");
        }
    }

}
你可以尝试使用

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

未经身份验证的页面
认证页

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

Spring论坛的一位成员为我提供了一个漂亮而优雅的解决方案。这是:

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

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

它非常好,因为它依赖于Spring Security。请看这里()

我可以想出几种方法来实现您的目标

首先,您可以利用Spring安全性标记库有条件地呈现视图模板中的内容,具体取决于用户是否经过正确的身份验证。有关Spring安全性标记库的更多信息,请参阅。粗略地说,这会使视图模板看起来像:

if(user is authenticated)
     render content for authenticated user
else
     render log-in form
然而,这感觉有点生硬,因为无论用户是否正确验证,控制器总是在创建模型。当您想要显示登录表单时,也需要在视图模板中使用此逻辑

另一种方法是创建一个实现,将所有请求转发给负责呈现登录页面的控制器,直到用户完全通过身份验证。您可以使用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
{

}}

然后,您可以配置SpringMVC将HandlerInterceptor实现映射到需要此功能的URL上。这样可以避免在所有控制器上复制逻辑,并且易于测试。

您应该这样做:

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

@RequestMapping("/")
@PreAuthorize("isAuthenticated()")
public String secureHomePage() {
    ...
}

谢谢kpentchev,这是一个有趣的想法。然而,这意味着我必须在我的控制器上复制这种逻辑……是的,从我的角度来看,这也是一个主要问题。也许可以将其移动到一个过滤器/拦截器,该过滤器/拦截器重定向到您的web应用程序的子部分,例如“/authorized/view”vs“/unauthorized/view”。从这里开始,授权视图应该只指向其他授权视图,等等……我确信SpringSecurity允许一种更简单的方法来实现所需的行为。我会在这里张贴,如果我发现相关的东西。谢谢KPentchev。如果您想向用户显示不同的对象集,比如说需要特定权限的项目子集,那么域对象安全性(ACL)可能是一个不错的选择。谢谢Josef。您的第二个答复与Kpenchev的建议非常相似,不幸的是,它并不真正依赖Spring Security。抱歉。它没有我想象的那么好。在更仔细地阅读了这篇文章之后,我意识到为了使这个解决方案发挥作用,我必须集成第三方类,而我不希望这样做。。。