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

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

问题描述

这是我的春季安全配置:

 < http pattern =/ auth /登录security =none/> 
< http pattern =/ auth / loginFailedsecurity =none/>
< http pattern =/ resources / **security =none/>

< http auto-config =trueaccess-decision-manager-ref =accessDecisionManager>
< intercept-url pattern =/ auth / logoutaccess =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 / logoutlogout-success-url =/ auth / login/>
< / http>

authenticationSuccessHandler 扩展 SavedRequestAwareAuthenticationSuccessHandler 确保将用户重定向到他最初请求的页面。



但是,因为 / auth / login 标记为 security =none,如果用户在登录后访问登录页面,我无法成功将用户重定向到主页in。我相信这是正确的用户体验



我也尝试了以下内容,但 Principal 对象始终是 null ,大概是因为 security =none属性。



< pre class =lang-java prettyprint-override> @RequestMapping(value =/ auth / login,method = GET)
public String showLoginForm(HttpServletRequest request,Principal principal){
I f(校长!= null){
returnredirect:/;
}

返回登录;
}


解决方案

我查看过主题比上次更深刻,发现你必须确定用户是否在控制器中自己进行了身份验证。 Row Winch(Spring Security dev)在这里说


Spring Security不知道您的应用程序的内部结构
(即如果你想要的话)根据用户是否登录用户
,使登录页面变为flex。要在登录页面请求
并且用户已登录时显示您的主页,请使用
中的 SecurityContextHolder 登录页面(或其控制器)并将用户重定向或转发到
主页。


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



applicationContext-security.xml

 < http auto-config =trueuse-expressions =true
access-decision-manager-ref =accessDecisionManager>
< intercept-url pattern =/ auth / loginaccess =permitAll/>
< intercept-url pattern =/ auth / logoutaccess =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 / logoutlogout-success-url =/ auth / login/>
< / http>

< beans:bean id =defaultTargetUrlclass =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 =defaultTargetUrlref =defaultTargetUrl/>
< / beans:bean>

添加到 applicationContext.xml bean定义:

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

这是类

  public final class SecurityContextAccessorImpl 
实现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 interface。)



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

  @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()){
返回登录;
} else {
returnredirect:+ defaultTargetUrl;
}
}
}

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


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>

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

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.

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

解决方案

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 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.

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>

Add to applicationContext.xml bean definition:

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

which is class

public final class SecurityContextAccessorImpl
      implements SecurityContextAccessor {

  @Autowired
  private AuthenticationTrustResolver authenticationTrustResolver;

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

implementing simple interface

public interface SecurityContextAccessor {
  boolean isCurrentAuthenticationAnonymous();
}

(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;
    }
  }
}

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天全站免登陆