java Spring security“转发:”指令无法转发到登录表单
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4824395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring security "forward:" directive can't forward to login form
提问by David Parks
After a user creates their account, I want to log that user on automatically.
在用户创建他们的帐户后,我想自动登录该用户。
I have standard form logins being handled by Springs filter on /postlogin
. If I go to http://localhost/postlogin
it attempts to log me in (fails because I didn't include the post parameters), but makes the proper attempt.
我有标准表单登录由 Springs 过滤器处理/postlogin
。如果我去,http://localhost/postlogin
它会尝试让我登录(失败,因为我没有包含 post 参数),但会进行适当的尝试。
But if I want to log the user in programatically and I try to return from the controller: "forward:/postlogin" I get a 404.
但是,如果我想以编程方式登录用户并尝试从控制器返回:“forward:/postlogin”,我会收到 404。
I assume the forward: directive is not passing through the filters, thus not getting handled by the UsernamePasswordAuthenticationFilter
.
我假设 forward: 指令没有通过过滤器,因此不会被UsernamePasswordAuthenticationFilter
.
How do I manually induce a login programatically? I want to do this after the user creates a new account (they should be logged into that account immediately upon completion of the registration).
如何以编程方式手动诱导登录?我想在用户创建新帐户后执行此操作(他们应在完成注册后立即登录该帐户)。
回答by David Parks
I mis-read another piece of guidance and realized that the correct way of handling this is the following:
我误读了另一篇指南,并意识到处理此问题的正确方法如下:
1) Manually set the Authentication token on SecurityContextHolder
1) 在 SecurityContextHolder 上手动设置身份验证令牌
UsernamePasswordWithAttributesAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( loadUserByUsername(username), password, authorities );
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
2) Do Notrender a page at this point or use the forward: directive. You must use the redirect: directive.
2) 此时不要渲染页面或使用 forward: 指令。您必须使用重定向:指令。
return "redirect:/accountcreated";
If you render a page the page will load fine, but the session object will be lost because a new j_session_id will be created but will not make it to the browser mid-request and the next request will use the old j_session_id, loosing the new session object & authetication.
如果您渲染页面,页面将正常加载,但会话对象将丢失,因为将创建新的 j_session_id 但不会在请求中途将其发送到浏览器,并且下一个请求将使用旧的 j_session_id,从而丢失新会话对象和认证。
Using the forward: directive will bypass the authentication filters, no good.
使用 forward: 指令将绕过身份验证过滤器,不好。
But redirect: causes the updated session information to make it to the browser.
但是重定向:导致更新的会话信息使其进入浏览器。
回答by AlexK
The new filtering feature in Servlet 2.4 basically alleviates the restriction that filters can only operate in the request flow before and after the actual request processing by the application server. Instead, Servlet 2.4 filters can now interact with the request dispatcher at every dispatch point. This means that when a Web resource forwards a request to another resource (for instance, a servlet forwarding the request to a JSP page in the same application), a filter can be operating before the request is handled by the targeted resource. It also means that should a Web resource include the output or function from other Web resources (for instance, a JSP page including the output from multiple other JSP pages), Servlet 2.4 filters can work before and after each of the included resources. .
Servlet 2.4 新增的过滤特性基本上缓解了过滤器只能在应用服务器实际处理请求前后的请求流中操作的限制。相反,Servlet 2.4 过滤器现在可以在每个调度点与请求调度器交互。这意味着当 Web 资源将请求转发到另一个资源时(例如,servlet 将请求转发到同一应用程序中的 JSP 页面),过滤器可以在目标资源处理请求之前运行。这也意味着如果一个 Web 资源包括来自其他 Web 资源的输出或功能(例如,一个 JSP 页面包括来自多个其他 JSP 页面的输出),Servlet 2.4 过滤器可以在每个包含的资源之前和之后工作。.
To turn on that feature you need:
要打开该功能,您需要:
web.xml
网页.xml
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/<strike>*</strike></url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
RegistrationController
注册控制器
return "forward:/login?j_username=" + registrationModel.getUserEmail()
+ "&j_password=" + registrationModel.getPassword();
回答by Nikita Bosik
Spring authentication via REST (Jersey)
通过 REST(泽西岛)进行 Spring 身份验证
Just to illustrate @David's answer (simplified as much as possible):
只是为了说明@David 的回答(尽可能简化):
@POST
@Path("login")
public Response login(@FormParam("login") String login, @FormParam("pass") String pass)
{
if (yourCheck(login, pass))
{
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
Authentication auth = new UsernamePasswordAuthenticationToken(login, pass, authorities);
SecurityContextHolder.getContext().setAuthentication(auth);
// IMPORTANT: Do not pass any data in the response body
// show empty 200 page (suitable for REST clients)
return Response.ok().build();
// or redirect to your home page (for web UI)
return Response.temporaryRedirect(new URI("/homepage/")).build();
}
else
{
return Response.status(Status.UNAUTHORIZED).build();
}
}