如果用户登录后访问登录页面,如何重定向到主页? [英] How to redirect to the homepage if the user accesses the login page after being logged in?

查看:20
本文介绍了如果用户登录后访问登录页面,如何重定向到主页?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的 spring 安全配置:

Here is my spring security config:

<http pattern="/auth/login" security="none" />
<http pattern="/auth/loginFailed" security="none" />
<http pattern="/resources/**" security="none" />

<http auto-config="true" access-decision-manager-ref="accessDecisionManager">
    <intercept-url pattern="/auth/logout" access="permitAll"/>
    <intercept-url pattern="/admin/**" access="ADMINISTRATIVE_ACCESS"/>
    <intercept-url pattern="/**" access="XYZ_ACCESS"/>

    <form-login
        login-page="/auth/login"
        authentication-failure-url="/auth/loginFailed"
        authentication-success-handler-ref="authenticationSuccessHandler" />
    <logout logout-url="/auth/logout" logout-success-url="/auth/login" />
</http>

authenticationSuccessHandler 扩展了 SavedRequestAwareAuthenticationSuccessHandler,确保用户被重定向到他最初请求的页面.

The authenticationSuccessHandler extends the SavedRequestAwareAuthenticationSuccessHandler ensuring that the user is redirected to the page he originally requested.

但是,由于 /auth/login 被标记为 security="none",如果他访问登录页面,我无法成功将用户重定向到主页登录后.我相信这是正确的 用户体验也是如此.

However, since /auth/login is marked as security="none", I am unable to successfully redirect the user to the homepage if he accesses the login page after being logged in. I believe this is the right user experience too.

我也尝试了以下方法,但 Principal 对象始终为 null,大概是因为再次使用 security="none" 属性.

I tried the below too but the Principal object is always null, presumably because of the security="none" attribute again.

@RequestMapping(value = "/auth/login", method = GET)
public String showLoginForm(HttpServletRequest request, Principal principal) {
    if(principal != null) {
        return "redirect:/";
    }

    return "login";
}

推荐答案

我比上次更深入地检查了该主题,发现您必须在控制器中确定用户是否通过自己的身份验证.Row Winch (Spring Security dev) 在这里说:

I've checked the topic more deeply than last time and found that you have to determine if user is authenticated by yourself in controller. Row Winch (Spring Security dev) says here:

Spring Security 不知道您的应用程序的内部结构(即,如果您想让您的登录页面基于用户是否灵活是否登录).在登录页面时显示您的主页请求并且用户使用 SecurityContextHolder 登录登录页面(或其控制器)并将用户重定向或转发到主页.

Spring Security is not aware of the internals of your application (i.e. if you want to make your login page flex based upon if the user is logged in or not). To show your home page when the login page is requested and the user is logged in use the SecurityContextHolder in the login page (or its controller) and redirect or forward the user to the home page.

因此,解决方案是确定请求 /auth/login 的用户是否匿名,如下所示.

So solution would be determining if user requesting /auth/login is anonymous or not, something like below.

applicationContext-security.xml:

<http auto-config="true" use-expressions="true"
        access-decision-manager-ref="accessDecisionManager">
    <intercept-url pattern="/auth/login" access="permitAll" />
    <intercept-url pattern="/auth/logout" access="permitAll" />
    <intercept-url pattern="/admin/**" access="ADMINISTRATIVE_ACCESS" />
    <intercept-url pattern="/**" access="XYZ_ACCESS" />

    <form-login login-page="/auth/login"
        authentication-failure-url="/auth/loginFailed"
        authentication-success-handler-ref="authenticationSuccessHandler" />
    <logout logout-url="/auth/logout" logout-success-url="/auth/login" />
</http>

<beans:bean id="defaultTargetUrl" class="java.lang.String">
    <beans:constructor-arg value="/content" />
</beans:bean>

<beans:bean id="authenticationTrustResolver"
        class="org.springframework.security.authentication.AuthenticationTrustResolverImpl" />

<beans:bean id="authenticationSuccessHandler"
        class="com.example.spring.security.MyAuthenticationSuccessHandler">
    <beans:property name="defaultTargetUrl" ref="defaultTargetUrl" />
</beans:bean>

添加到 applicationContext.xml bean 定义:

Add to applicationContext.xml bean definition:

<bean id="securityContextAccessor"
    class="com.example.spring.security.SecurityContextAccessorImpl" />

哪个是类

public final class SecurityContextAccessorImpl
      implements SecurityContextAccessor {

  @Autowired
  private AuthenticationTrustResolver authenticationTrustResolver;

  @Override
  public boolean isCurrentAuthenticationAnonymous() {
    final Authentication authentication =
        SecurityContextHolder.getContext().getAuthentication();
    return authenticationTrustResolver.isAnonymous(authentication);
  }
}

实现简单的界面

public interface SecurityContextAccessor {
  boolean isCurrentAuthenticationAnonymous();
}

(SecurityContextHolder 访问代码与控制器分离,我遵循了这个答案的建议,因此 SecurityContextAccessor 接口.)

(SecurityContextHolder accessing code is decoupled from controller, I followed suggestion from this answer, hence SecurityContextAccessor interface.)

最后但并非最不重要的是控制器中的重定向逻辑:

And last but not least redirect logic in controller:

@Controller
@RequestMapping("/auth")
public class AuthController {
  @Autowired
  SecurityContextAccessor securityContextAccessor;

  @Autowired
  @Qualifier("defaultTargetUrl")
  private String defaultTargetUrl;

  @RequestMapping(value = "/login", method = RequestMethod.GET)
  public String login() {
    if (securityContextAccessor.isCurrentAuthenticationAnonymous()) {
      return "login";
    } else {
      return "redirect:" + defaultTargetUrl;
    }
  }
}

定义 defaultTargetUrl 字符串 bean 看起来像一个黑客,但我没有更好的方法不对 url 进行硬编码......(实际上在我们的项目中我们使用 <util:constant> 包含静态 final String 字段的类.)但它毕竟有效.

Defining defaultTargetUrl String bean seems like a hack, but I don't have better way not to hardcode url... (Actually in our project we use <util:constant> with class containing static final String fields.) But it works after all.

这篇关于如果用户登录后访问登录页面,如何重定向到主页?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆