AccessDeniedHandler,重定向到登录页面

时间:2017-01-12 09:57:30

标签: spring spring-mvc spring-security

当(在Spring Security / MVC中)对页面的访问被拒绝时,由于用户没有足够的权限(虽然他经过身份验证),我需要通过显示登录页面提供以另一个用户身份登录(而不是显示403访问被拒绝页面的标准行为。) 我可以写一个AccessDeniedHandler,重定向到登录页面。但是当Spring Security发现有另外一个用户登录时会如何反应?当新用户成功通过身份验证后,我可以以某种方式注销旧用户吗?

3 个答案:

答案 0 :(得分:2)

我已经尝试在已有其他用户登录时登录新用户。它可以正常工作 - 无需注销第一个用户。他的授权被新的授权所取代。这是我自己问题的简单答案。

如果有人感兴趣,如果访问被拒绝,如何转发登录页面 - 这是我的解决方案:

首先定义一个自定义RequestCache:

@Component("myRequestCache")
public class MyRequestCache extends HttpSessionRequestCache {
    public MyRequestCache() {
        super();
    }
}

其次定义自定义AccessDeniedHandler:

@Component("myAccessDeniedHandler")
public class MyAccessDeniedHandler implements AccessDeniedHandler {

    @Autowired
    @Qualifier("myRequestCache")
    private RequestCache myRequestCache;

    public MyAccessDeniedHandler() {
    }

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc)
        throws IOException, ServletException {

        if (!response.isCommitted()) {

            //Save Target-Request
            shopRequestCache.saveRequest(request, response);

            //Forward to the login page
            request.getRequestDispatcher("/loginPage").forward(request, response);
        }
    }   
}

第三步将这两个配置为Spring Security:

@Configuration
@EnableWebSecurity
public class myConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("myRequestCache")
    RequestCache myRequestCache;

    @Autowired
    @Qualifier("myAccessDeniedHandler")
    AccessDeniedHandler myAccessDeniedHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
        .requestCache()
            .requestCache(myRequestCache)
            .and()
        .exceptionHandling()
            .accessDeniedHandler(myAccessDeniedHandler)
    }
}

这里发生了什么?
MyAccessDeniedHandler转发到AccessDeniedException登录页面。由于这个转发是由这个自编程类调用的,而不是由过滤器链中的Spring调用,我们必须告诉spring,目标请求是什么 - 在成功验证后必须重定向的位置。我们通过RequestCache进行此操作。

答案 1 :(得分:0)

如果您要退出旧用户,我建议您使用SessionRegistryhttp://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/core/session/SessionRegistry.html

一些提示:

在Spring配置类

@Configuration
class MyConfiguration{
   @Bean
   public SessionRegistry sessionRegistry() {
      return new SessionRegistryImpl();
   }
}

AccessDeniedHandler

@Autowired
private SessionRegistry sessionRegistry;

....
List<SessionInformation> sessionInformations = sessionRegistry.getAllSessions("an-user", false);
    for(SessionInformation session: sessionInformations) {
        session.expireNow();
    }

答案 2 :(得分:-1)

您可以在spring security xml文件中添加以下标记。

<http auto-config="true" use-expressions="true">
          <access-denied-handler error-page="/accessDenied" />
         <intercept-url pattern="/publicIndex1" access="isAnonymous()"/>
         <intercept-url pattern="/index1" access="isAnonymous()"/>
         <!-- Restrict URLs based on role -->
        <intercept-url pattern="/#/publicIndex" access="isAnonymous()" />

    <form-login  
        login-page="/publicIndex1" 
        always-use-default-target="false"
        default-target-url="/index"     
        authentication-failure-url="/publicIndex1" 
        username-parameter="username"
        password-parameter="password" />
    <logout logout-success-url="/index1" 
    delete-cookies="JSESSIONID" 
    logout-url="/logout" 
    invalidate-session="true" />
</http>

在你的弹簧控制器中。

@RequestMapping(value = "/accessDenied", method = RequestMethod.GET)
public ModelAndView accessDenied() {
    System.out.println("access denied page call");
    return new ModelAndView("accessDenied");
}

@RequestMapping(value = "/#/publicIndex", method = RequestMethod.GET)
public ModelAndView login(@RequestParam(value = "error", required = false) String error,
        @RequestParam(value = "logout", required = false) String logout) {
    System.out.println("inside /#/public index");
    ModelAndView model = new ModelAndView();
    if (error != null) {
        model.addObject("error", "Invalid username and password!");
    }
    System.out.println("**********************" + error);
    if (logout != null) {
        model.addObject("msg", "You've been logged out successfully.");
    }
    model.setViewName("publicIndex");
    return model;
}

@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout1() {
    System.out.println();
    User user1 = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    return userService.addUserOffline(user1.getUserId());
}

@RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView index() {
    System.out.println("Redirect Controller Call");
    User user = new User();
    try {
        user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    } catch (Exception e) {
        return new ModelAndView("publicIndex1");
    }
    long userId = user.getUserId();
    userService.addLastLoginDate(userId);
    System.out.println("user id==" + userId);
    return new ModelAndView("index");

}

@RequestMapping(value = "/index1", method = RequestMethod.GET)
public ModelAndView index1() {
    System.out.println("inside logout index1");
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (!(auth instanceof AnonymousAuthenticationToken)) {
        return new ModelAndView("/index");
    } else {
        return new ModelAndView("index1");
    }
}
相关问题