登录到Spring MVC应用程序时的java自定义响应
登录到SpringMVC应用程序需要自定义响应
当前感知用户的合理默认响应似乎是302,其中“Location:”头指向应用程序的所需部分
如果web应用程序恰好是一个单页应用程序,因此不需要实际重定向到任何地方,该怎么办
到目前为止,我已经成功地使用了两个过滤器:一个在用户名密码身份验证过滤器之前,另一个在过滤器安全Interceptor类之后
在代码中,前者扩展AbstractAuthenticationProcessingFilter并处理凭证和存储会话属性,而后者则查找该属性,如果存在,则最终将使用所需的响应数据进行响应(稍后还会从会话中删除该属性)
到目前为止,过滤器对的好的一面是,可以对登录请求编写自定义响应。此外,新会话已正确初始化,我们可以重用现有会话固定策略
所述两个过滤器方法的问题:
重定向将发生回web应用程序的根(“/”),尽管可以重置缓冲区并写入自定义数据(一个简单的JSON响应)——覆盖重定向没有成功
并行执行的任何请求都将获得该自定义数据(必须注意,在经过身份验证之前,不得向应用程序的任何其他路径发出任何其他请求;
当在筛选时完成时,用户权限还未知。在通过AuthenticationProvider传递凭据之前,不知道响应的状态代码
额外问题:如果出于某种原因,好的旧用户名和密码过滤器也需要合作,该怎么办
我还不能将完整的代码粘贴到最小的应用程序中,但到目前为止,Spring Security conf在扩展WebSecurity ConfigureAdapter的配置类中有以下内容:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.cors()
.disable()
.httpBasic()
.disable()
.formLogin()
.disable()
.authorizeRequests()
.antMatchers("/")
.permitAll()
.antMatchers("/auth/**")
.permitAll()
.antMatchers("/js/**")
.permitAll()
.antMatchers("/welcome")
.hasAuthority(MyAuthenticationProvider.AUTH_WELCOME.getAuthority())
.anyRequest()
.authenticated()
.and()
.addFilterBefore(getMyAuthenticationFilter("/auth/login"), UsernamePasswordAuthenticationFilter.class)
.addFilterAfter(getMyResponseFilter(), FilterSecurityInterceptor.class)
.logout()
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.logoutSuccessUrl("/");
}
private Filter getMyAuthenticationFilter(String loginUrl) {
return new MyAuthenticationProcessingFilter(loginUrl);
}
private Filter getMyResponseFilter() {
return new MyAuthenticationReplyFilter();
}
和过滤器如下所示:
package org.so.example;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.so.example.auth.TokenHolder;
import org.so.example.auth.MyAuthenticationToken;
public class MyAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
private static final Logger LOG = LoggerFactory.getLogger(MyAuthenticationProcessingFilter.class);
protected static final String MY_RESPONSE_DATA = "MY_RESPONSE_DATA";
public MyAuthenticationProcessingFilter(String defaultFilterProcessesUrl) {
super(defaultFilterProcessesUrl);
LOG.info("Created MyAuthenticationProcessingFilter {}", defaultFilterProcessesUrl);
}
public MyAuthenticationProcessingFilter(RequestMatcher requestMatcher) {
super(requestMatcher);
LOG.info("Created MyAuthenticationProcessingFilter {}", requestMatcher);
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
LOG.info("doFilter");
super.doFilter(req, res, chain);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException, IOException, ServletException {
if (!"POST".equals(req.getMethod())) {
throw new InsufficientAuthenticationException("POST only please");
}
// TODO authenticate the request and compose data
// Once here, need to reply with My specific response
// At moment there is another filter for that (farther in chain for always returning a success with detected user name).
// however the user has not been authorized to do anything yet.
// No idea what http status code to respond with.
HttpServletRequest request = (HttpServletRequest) req;
request.getSession().setAttribute(MY_RESPONSE_DATA, sub);
return new MyAuthenticationToken(sub, parsedToken);
}
}
package org.so.example;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.filter.GenericFilterBean;
/**
* This filter is meant to be last in chain to provide special kind of authentication response
*/
public class MyAuthenticationReplyFilter extends GenericFilterBean {
private static final Logger LOG = LoggerFactory.getLogger(MyAuthenticationReplyFilter.class);
public MyAuthenticationReplyFilter() {
LOG.info("Constructing special reply filter");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
LOG.info("doFilter");
if (res.isCommitted()) {
LOG.warn("How come response is already committed at filter time?");
chain.doFilter(req, res);
} else {
HttpServletRequest request = (HttpServletRequest) req;
String userName = (String) request
.getSession()
.getAttribute(MyAuthenticationProcessingFilter.MY_RESPONSE_DATA);
if (userName != null) {
HttpServletResponse response = (HttpServletResponse) res;
response.setContentType("application/json; charset=UTF-8");
response.setStatus(200);
response.resetBuffer();
//TODO sanitize data set by authentication processing filter
response.getWriter().write("{\"great\" : \"success\", \"sub\": \"" + userName + "\"}");
LOG.info("Responded with http 200 and some json instead of redirection");
request.getSession().removeAttribute(MyAuthenticationProcessingFilter.MY_RESPONSE_DATA);
} else {
chain.doFilter(req, res);
}
}
}
}```
共 (0) 个答案