• SpringSecurity 增加Filter过滤器


    配置类

    package com.imooc.security.browser;
    
    import com.imooc.security.core.properties.SecurityProperties;
    import com.imooc.security.core.validate.code.ValidateCodeFilter;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
    import org.springframework.security.web.authentication.AuthenticationFailureHandler;
    import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    
    @Configuration
    public class BrowserSecurityConfig  extends WebSecurityConfigurerAdapter {
        @Autowired
        private AuthenticationSuccessHandler imoocAuthenticationSuccessHandler;
        @Autowired
        private AuthenticationFailureHandler imoocAuthenctiationFailureHandler;
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new SCryptPasswordEncoder();
        }
    
        @Autowired
        private SecurityProperties securityProperties;
    
        @Override
        public void configure(HttpSecurity http) throws Exception {
            // 验证码过滤器
            ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
            validateCodeFilter.setAuthenticationFailureHandler(imoocAuthenctiationFailureHandler);
            validateCodeFilter.setSecurityProperties(securityProperties);
            validateCodeFilter.afterPropertiesSet();
            // 添加一个图片验证filter, 在UsernamePasswordAuthenticationFilter之前执行
            http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                    // .httpBasic() // 默认方式
                    .formLogin() // 设置认证的登录方式 表单方式
                    .loginPage("/authentication/require") // 自定义登录页面
                    .loginProcessingUrl("/authentication/form") // 自定义表单url, 默认是login
                    .successHandler(imoocAuthenticationSuccessHandler) // 不适用默认的认证成功处理器
                    .failureHandler(imoocAuthenctiationFailureHandler) // 登录失败处理器
    //                .failureForwardUrl("/authentication/require")
    //                .failureUrl("/authentication/require")
                    .and()
                    .authorizeRequests() // 需要授权
                    // 当匹配到这个页面时,不需要授权
                    .antMatchers("/authentication/require", securityProperties.getBrowser().getLoginPage(),
                            "/code/image").permitAll()
                    .anyRequest() // 所有请求
                    .authenticated()
            .and()  // 关闭csrf
            .csrf()
            .disable();
        }
    }
    

      Filter

    package com.imooc.security.core.validate.code;
    
    
    import com.imooc.security.core.properties.SecurityProperties;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.security.web.authentication.AuthenticationFailureHandler;
    import org.springframework.social.connect.web.HttpSessionSessionStrategy;
    import org.springframework.social.connect.web.SessionStrategy;
    import org.springframework.util.AntPathMatcher;
    import org.springframework.web.bind.ServletRequestBindingException;
    import org.springframework.web.bind.ServletRequestUtils;
    import org.springframework.web.context.request.ServletWebRequest;
    import org.springframework.web.filter.OncePerRequestFilter;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * OncePerRequestFilter 只会调用一次Filter
     */
    public class ValidateCodeFilter extends OncePerRequestFilter implements InitializingBean {
        private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
    
        private Set<String> urls = new HashSet<>();
        private SecurityProperties securityProperties;
        public void setSecurityProperties(SecurityProperties securityProperties) {
            this.securityProperties = securityProperties;
        }
        private AuthenticationFailureHandler authenticationFailureHandler;
    
        private AntPathMatcher pathMatcher = new AntPathMatcher();
    
        // 加载完配置文件之后,获取所有需要使用验证码的url
        @Override
        public void afterPropertiesSet() throws ServletException {
            super.afterPropertiesSet();
            String[] configUrls = StringUtils.splitByWholeSeparatorPreserveAllTokens(securityProperties.getCode().getImage().getUrl(), ",");
            for (String url : configUrls) {
                urls.add(url);
            }
            urls.add("/authentication/form");
        }
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
           boolean action = false;
            for (String url : urls) {
                if (pathMatcher.match(url, request.getRequestURI()))
                    action = true;
            }
            if (action) {
                try {
                    validate(new ServletWebRequest(request));
                } catch (ValidateCodeException e) {
                    authenticationFailureHandler.onAuthenticationFailure(request, response, e);
                    return;
                }
            }
            filterChain.doFilter(request, response);
        }
    
        public void validate(ServletWebRequest request) throws ServletRequestBindingException {
    
            ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(request, ValidateCodeController.SESSION_KEY);
            String codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), "imageCode");
            if (StringUtils.isBlank(codeInRequest)) {
                throw new ValidateCodeException( "验证码的值不能为空");
            }
    
            if (codeInRequest == null) {
                throw new ValidateCodeException( "验证码不存在");
            }
    
            if (codeInSession.isExpried()) {
                sessionStrategy.removeAttribute(request,  ValidateCodeController.SESSION_KEY);
                throw new ValidateCodeException( "验证码已过期");
            }
    
            if (!StringUtils.equals(codeInSession.getCode(), codeInRequest)) {
                throw new ValidateCodeException( "验证码不匹配");
            }
    
            sessionStrategy.removeAttribute(request, ValidateCodeController.SESSION_KEY);
        }
        public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
            this.authenticationFailureHandler = authenticationFailureHandler;
        }
    
    }
    

      

  • 相关阅读:
    摇骰子游戏
    那些年,产品提出的无理需求
    cookie中数据无法读取,HttpOnly属性
    vue 使用字典值及其翻译
    微信小程序picker组件两列关联使用方式
    fatal: unable to access 'https://github.com/xxxxxgit/': OpenSSL SSL_connect: Connection was reset in connection to github.com:443
    Oracle数据库以date类型保存日期时 nvalid request: Out of range property; SalesOrder.date'
    Event Handler Content must support at least one class.
    Minimum length not met: value 0 < 1 minimum length
    Oracle中使用hash_hmac() 函数报错问题/以及Oracle遇到Oauth1.0授权和oauth_signature生成规则
  • 原文地址:https://www.cnblogs.com/412013cl/p/14066393.html
Copyright © 2020-2023  润新知