有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

登录到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) 个答案