简体   繁体   English

Spring Security - 使用 java 配置的自定义预授权过滤器

[英]Spring Security - Custom Pre Auth filter using java config

I am trying to configure a simple custom authentication filter that checks for a token on every page of the web app except the '/login' page.我正在尝试配置一个简单的自定义身份验证过滤器,用于检查 Web 应用程序除“/登录”页面之外的每个页面上的令牌。 Right now, the filter is up and running, but no matter what settings I change, the filter is being called on every page, including '/login' which I have set to permitAll().现在,过滤器已启动并运行,但无论我更改什么设置,都会在每个页面上调用过滤器,包括我已设置为 permitAll() 的“/login”。

When I access localhost:8080/login, I expect it to not call this filter based on my configuration below, but instead it throws an exception in the filter because no session is found.当我访问 localhost:8080/login 时,我希望它不会根据我下面的配置调用此过滤器,而是在过滤器中抛出异常,因为没有找到会话。

My question is how do I limit the filter to all pages except the '/login' page?我的问题是如何将过滤器限制为除“/登录”页面之外的所有页面?

Here is my config:这是我的配置:

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

private UserDetailsService userDetailsService;
private PreAuthenticatedAuthenticationProvider preAuthenticatedProvider;

public SecurityConfig() {
    super();

    userDetailsService = new UserDetailsServiceImpl();
    UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken> wrapper = 
            new UserDetailsByNameServiceWrapper<PreAuthenticatedAuthenticationToken>(userDetailsService);

    preAuthenticatedProvider = new PreAuthenticatedAuthenticationProvider();
    preAuthenticatedProvider.setPreAuthenticatedUserDetailsService(wrapper);
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(preAuthenticatedProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    OpenTokenRequestAuthenticationFilter filter = new OpenTokenRequestAuthenticationFilter();
    filter.setAuthenticationManager(authenticationManager());


    http
        .addFilter(filter)
        .authorizeRequests()
            .antMatchers("/login").permitAll();
}

}

And here is the filter:这是过滤器:

    public class OpenTokenRequestAuthenticationFilter extends
        AbstractPreAuthenticatedProcessingFilter {

    /**
     * logger for the class
     */
    private static final Logger logger = LoggerFactory.getLogger(OpenTokenRequestAuthenticationFilter.class);

    @Autowired
    private ExceptionMappingAuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    private IOpenTokenReader openTokenReader;

    private String logoutURL;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)request;
        HttpServletResponse httpServletResponse = (HttpServletResponse)response;
        super.doFilter(httpServletRequest, httpServletResponse, chain);
        HttpSession session = httpServletRequest.getSession(false);
        if(session != null && session.getAttribute("ssoToken") != null)
        {
            SsoToken ssoToken = (SsoToken)session.getAttribute("ssoToken");
            httpServletResponse.addHeader("agentName", ssoToken.getName());
            httpServletResponse.addHeader("agentID", ""+ssoToken.getLoginId());
        }
    }

    /**
     * 
     */
    protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
        String principal = null;
        HttpSession session = null;

        try {
            session = request.getSession(false);
            String tokenName = openTokenReader.getTokenName();

            if (tokenName != null && request.getParameter(tokenName.trim()) != null && !request.getParameter(tokenName.trim()).isEmpty()) {
                logger.info("Token found in request. Token Name:  "+ tokenName);
                SsoToken ssoToken = null;
                if (session != null) {
                    session.invalidate();
                    logger.info("Invalidated old session and creating a new session since request found with new token.");
                }
                session = request.getSession(true);//create new session
                logger.info("New session created: "+session.getId());

                Agent agent = openTokenReader.getAgent();
                Map result = agent.readToken(request);
                if (result != null) {
                    principal = (String) result.get("subject");
                    ssoToken = new SsoToken();
                    ssoToken.setLogoutURL(getLogoutURL());
//                  ssoToken.setName((String) result.get("lastName") +", "+(String) result.get("firstName"));
                    ssoToken.setName((String) result.get("firstName"));
                    ssoToken.setAffiliate((result.get("isAffiliate") != null && !((String)result.get("isAffiliate")).trim().equals("false")) ? true : false);
                    if(ssoToken.isAffiliate())
                        ssoToken.setLoginId((String) result.get("affiliateId"));
                    else
                        ssoToken.setLoginId((String) result.get("subject"));
                }
                session.setAttribute("ssoToken", ssoToken);
                boolean isInValidToken = hasInvalidTokenData(ssoToken);
                if (isInValidToken) {
                    throw new PreAuthenticatedCredentialsNotFoundException("Invalid Token found in request.");
                } else {
                    session.setAttribute("hasValidToken", true);
                }
            }

        } catch (Exception e) {
            logger.error("Exception while reading token " + e);
        }
        if(session == null )
            throw new PreAuthenticatedCredentialsNotFoundException("No session found.");
        if(session != null && session.getAttribute("hasValidToken") == null)
            throw new PreAuthenticatedCredentialsNotFoundException("No attribute 'hasValidToken' found in session.");
        if(session != null && session.getAttribute("hasValidToken") != null && !(Boolean) session.getAttribute("hasValidToken"))
            throw new PreAuthenticatedCredentialsNotFoundException("value of  attribute 'hasValidToken' is false in session.");

        /*if (session == null || session.getAttribute("hasValidToken") == null || !((Boolean) session.getAttribute("hasValidToken"))){
            throw new PreAuthenticatedCredentialsNotFoundException("Token not found in request.");
        }*/
        if(session != null && session.getAttribute("ssoToken") != null)
        {
            SsoToken ssoToken = (SsoToken)session.getAttribute("ssoToken");
            principal = ssoToken.getLoginId();
        }

        return principal;
    }
    public boolean hasInvalidTokenData(SsoToken token) {
        boolean hasInvalidTokenData = false;
        if (token == null) {
            hasInvalidTokenData = true;
        } else {
            if (StringUtils.isBlank(token.getLoginId())) {
                logger.debug("Login ID was blank.");
                hasInvalidTokenData = true;
            }
        }
        if (logger.isDebugEnabled()) {
            logger.debug("Exiting: hasInvalidTokenData(SsoToken)");
            logger.debug("hasInvalidTokenData=|" + hasInvalidTokenData + "|");
        }
        return hasInvalidTokenData;
    }
    @Override
    protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
        return "";
    }

    /**
     * @return the logoutURL
     */
    public String getLogoutURL() {
        return logoutURL;
    }

    /**
     * @param logoutURL the logoutURL to set
     */
    public void setLogoutURL(String logoutURL) {
        this.logoutURL = logoutURL;
    }

    public void setAuthenticationFailureHandler(ExceptionMappingAuthenticationFailureHandler authenticationFailureHandler){
        this.authenticationFailureHandler = authenticationFailureHandler;
    }

    public ExceptionMappingAuthenticationFailureHandler getAuthenticationFailureHandler(){
        return authenticationFailureHandler;
    }

The below code Filters the unauthorized/Session expired requests for a particular endpoint.下面的代码过滤特定端点的未授权/会话过期请求。 The Bean should be configured along with the endpoint URL so the Auth filter will be applicable for that endpoint. Bean 应与端点 URL 一起配置,以便 Auth 过滤器适用于该端点。 Now by doing so you can restric the filter application for only the endpoints which you want.现在通过这样做,您可以将过滤器应用程序限制为仅用于您想要的端点。

@Bean
public FilterRegistrationBean<AuthFilter> filterRegistrationBean() {
        FilterRegistrationBean<AuthFilter> registrationBean = new FilterRegistrationBean<>();
        AuthFilter authFilter = new AuthFilter();
        registrationBean.setFilter(authFilter);
        // Include the URL patterns for which the Auth filter should be applicable 
        registrationBean.addUrlPatterns("/api/protectedendpoint/*");
        return registrationBean;
    }

Auth Filter授权过滤器

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.filter.GenericFilterBean;

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 java.io.IOException;


public class AuthFilter extends GenericFilterBean {
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String authHeader = httpRequest.getHeader("Authorization");
    if (authHeader != null) {
      String[] authHeaderArr = authHeader.split("Bearer ");
      if (authHeaderArr.length > 1 && authHeaderArr[1] != null) {
        String token = authHeaderArr[1];

        try {
          Claims claims = Jwts.parser().setSigningKey(YOUR_JWT_SECRET_KEY).parseClaimsJws(token).getBody();
          httpRequest.setAttribute("email", claims.get("email").toString());
        } catch (Exception e) {
          httpResponse.sendError(HttpStatus.FORBIDDEN.value(), "invalid/expired token");
          return;
        }
      } else {
        httpResponse.sendError(HttpStatus.FORBIDDEN.value(), "Authorization token must be Bearer [token]");
        return;
      }
    } else {
      httpResponse.sendError(HttpStatus.UNAUTHORIZED.value(), "Authorization token must be provided");
      return;
    }
    chain.doFilter(httpRequest, httpResponse);
  }
}```

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用Java Config的Spring Security自定义身份验证过滤器 - Spring Security custom authentication filter using Java Config 如何配置spring security 3.2以使用java配置使用dao身份验证和自定义身份验证过滤器 - How to configure spring security 3.2 to use dao authentication and custom authentication filter using java config Spring 安全性 - 使用带有 Auth0 预身份验证的自定义数据库授权 - Spring Security - Using custom DB authorization with Auth0 pre-authentication 如何使用Java配置表示Spring Security“自定义过滤器”? - How to represent the Spring Security “custom-filter” using Java configuration? Spring 安全性 - 自定义 AuthenticationProvider 不起作用 - Java Config - Spring security - Custom AuthenticationProvider not working - Java Config 结合使用Java配置和Spring Security进行基于注释的角色检查和基本HTTP身份验证 - Using Java config with Spring Security for annotation-based role checks and Basic HTTP Auth Spring Security Java配置 - Spring Security Java Config Java 配置 Spring Security FORM_LOGIN_FILTER - Java Config Spring Security FORM_LOGIN_FILTER Spring Security自定义过滤器 - Spring Security custom filter Spring Security Java Config自定义注销处理程序不起作用 - Spring Security Java Config Custom Logout Handler Not Working
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM