zoukankan      html  css  js  c++  java
  • 02.实现图形验证码

    实现图形验证码

    使用过滤器实现图形验证码

    使用kaptcha验证码

           <!--验证码组件-->
            <dependency>
                <groupId>com.github.penggle</groupId>
                <artifactId>kaptcha</artifactId>
                <version>2.3.2</version>
            </dependency>
    
    /**
     * 自定义身份验证失败处理程序
     */
    public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{"error_code":"401","name":""+e.getClass()+"","message":""+e.getMessage()+""}");
        }
    }
    
    public class VerificationCodeException extends AuthenticationException {
        public VerificationCodeException(){
            super("验证码校验失败");
        }
    }
    
    /**
     * 验证码过滤器
     * OncePerRequestFilter 确保一次请求只会通过一次该过滤器
     * 核对session中保存的验证码与用户提交的验证码是否一致
     * // /auth/form 登录请求才校验验证码
     *  {@link WebSecurityConfig}
     */
    public class VerificationCodeFilter extends OncePerRequestFilter  {
        private AuthenticationFailureHandler handler = new MyAuthenticationFailureHandler();
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
            if ("/auth/form".equals(request.getRequestURI())){
                try {
                    verificationCode(request);
                    filterChain.doFilter(request,response);
                }catch (VerificationCodeException e){
                    handler.onAuthenticationFailure(request,response,e);
                }
            }else {
                filterChain.doFilter(request,response);
            }
        }
    
        public void verificationCode(HttpServletRequest request) throws VerificationCodeException {
            String requestCode = request.getParameter("captcha");
            HttpSession session = request.getSession();
            String saveCode = (String) session.getAttribute("captcha");
            if (!StringUtils.isEmpty(saveCode)){
                //随手清除验证码
                session.removeAttribute("captcha");
            }
            //校验不通过,抛出异常
            if (StringUtils.isEmpty(requestCode)||StringUtils.isEmpty(saveCode)||!requestCode.equals(saveCode)){
                throw new VerificationCodeException();
            }
        }
    }
    
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
        @Bean
        public AuthenticationProvider authenticationProvider(){
            DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
            authenticationProvider.setUserDetailsService(userDetailsService());
            authenticationProvider.setPasswordEncoder(passwordEncoder());
            return authenticationProvider;
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/admin/api/**").hasRole("ADMIN")
                    .antMatchers("/user/api/**").hasRole("USER")
                    .antMatchers("/app/api/**", "/captcha","/captchaLogin.html").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin().loginPage("/captchaLogin.html")
                    .loginProcessingUrl("/auth/form")
                    .successHandler(new AuthenticationSuccessHandler() {
                        @Override
                        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                            httpServletResponse.setContentType("application/json;charset=UTF-8");
                            httpServletResponse.getWriter().write("{"error_code":"0","message":"欢迎登陆"}");
                        }
                    })
                    .failureHandler(new MyAuthenticationFailureHandler())
    //                .and().sessionManagement().maximumSessions(1)
    //                .and().and().csrf().disable();
                    .and().csrf().disable();
            http.addFilterBefore(new VerificationCodeFilter(), UsernamePasswordAuthenticationFilter.class);
        }
        @Bean
        public UserDetailsService userDetailsService(){
            InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
            manager.createUser(User.withUsername("user").password(new BCryptPasswordEncoder().encode("123")).roles("USER").build());
            manager.createUser(User.withUsername("admin").password(new BCryptPasswordEncoder().encode("123")).roles("ADMIN").build());
            return manager;
        }
    }
    

    测试

    @Controller
    @SpringBootApplication(scanBasePackages = "com.security.config.captchaConfig")
    public class Captchabootstrap {
        public static void main(String[] args) {
            SpringApplication.run(Captchabootstrap.class);
        }
        @Autowired
        private Producer captchaProducer;
        @Bean
        public Producer captcha(){
            Properties properties = new Properties();
            properties.setProperty("kaptcha.image.width","150");
            properties.setProperty("kaptcha.image.height","150");
            //字符集
            properties.setProperty("kaptcha.textproducer.char.string","0123456789");
            //字符长度
            properties.setProperty("kaptcha.textproducer.char.length","4");
            Config config = new Config(properties);
            DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
            defaultKaptcha.setConfig(config);
            return defaultKaptcha;
        }
    
        @GetMapping("/captcha")
        public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
            response.setContentType("image/jpeg");
            String capText = captchaProducer.createText();
            request.getSession().setAttribute("captcha",capText);
            BufferedImage bi = captchaProducer.createImage(capText);
            ServletOutputStream out = response.getOutputStream();
            ImageIO.write(bi,"jpg",out);
            try {
                out.flush();
            } finally {
                out.close();
            }
        }
    
        @GetMapping("/index")
        @ResponseBody
        public String index(){
            return "index";
        }
        @GetMapping("/admin/api")
        public String admin(){
            return "hello,admin";
        }
        @GetMapping("/user/api")
        public String user(){
            return "hello,user";
        }
        @GetMapping("/app/api")
        public String app(){
            return "hello,app";
        }
    }
    
    <body>
    <h1>login</h1>
    <div>
        username:<input id="username" type="text" name="username"><hr>
        password:<input id="password" type="password" name="password"><hr>
        <div style="display:flex;">
            <input type="text" name="captcha" id="captcha">
            <img src="/captcha" height="50px" width="150px" style="" alt="">
        </div>
        <button onclick="submit()">submit</button>
    </div>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script>
            function submit(){
                var username = $('#username').val();
                var password = $('#password').val();
                var captcha = $('#captcha').val();
                $.post("/auth/form",{username:username,password:password,captcha:captcha},function (res) {
                    if (res.error_code=='0'){
                        window.location.href="http://localhost:8080/index"
                    }
                })
            }
        </script>
    </body>
    

    使用自定义认证实现图形验证码

    public class MyWebAuthenticationDetails extends WebAuthenticationDetails {
        private boolean imageCodeIsRight;
        public boolean getImageCodeIsRight(){
            return imageCodeIsRight;
        }
    
        public MyWebAuthenticationDetails(HttpServletRequest request) {
            super(request);
            String imageCode = request.getParameter("captcha");
            HttpSession session = request.getSession();
            String saveImageCode = (String)session.getAttribute("captcha");
            if (!StringUtils.isEmpty(saveImageCode)){
                session.removeAttribute("captcha");
                if (!StringUtils.isEmpty(imageCode)&&imageCode.equals(saveImageCode)){
                    this.imageCodeIsRight = true;
                }
            }
        }
    }
    	
    
    @Component
    public class MyWebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
    
        @Override
        public WebAuthenticationDetails buildDetails(HttpServletRequest request) {
            return new MyWebAuthenticationDetails(request);
        }
    }
    
    
    public class MyAuthenticationProvider extends DaoAuthenticationProvider {
        public MyAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
            setUserDetailsService(userDetailsService);
            setPasswordEncoder(passwordEncoder);
        }
    
        /**
         * 其他身份验证检查
         * @param userDetails
         * @param authentication
         * @throws AuthenticationException
         */
        @Override
        protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
            MyWebAuthenticationDetails details = (MyWebAuthenticationDetails) authentication.getDetails();
            if (!details.getImageCodeIsRight()){
                throw new VerificationCodeException();
            }
            super.additionalAuthenticationChecks(userDetails, authentication);
        }
    }
    
    
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> myWebAuthenticationDetailsAuthenticationDetailsSource;
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
        @Bean
        public MyAuthenticationProvider myAuthenticationProvider(){
            return new MyAuthenticationProvider(userDetailsService(),passwordEncoder());
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(myAuthenticationProvider());
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
                    .antMatchers("/admin/api/**").hasRole("ADMIN")
                    .antMatchers("/user/api/**").hasRole("USER")
                    .antMatchers("/app/api/**", "/captcha","/captchaLogin.html").permitAll()
                    .anyRequest().authenticated()
                    .and()
                    .formLogin()
                    .authenticationDetailsSource(myWebAuthenticationDetailsAuthenticationDetailsSource)
                    .loginPage("/captchaLogin.html")
                    .loginProcessingUrl("/auth/form")
                    .successHandler(new AuthenticationSuccessHandler() {
                        @Override
                        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                            httpServletResponse.setContentType("application/json;charset=UTF-8");
                            httpServletResponse.getWriter().write("{"error_code":"0","message":"欢迎登陆"}");
                        }
                    })
                    .failureHandler(new MyAuthenticationFailureHandler())
                    .and().csrf().disable();
        }
        @Bean
        public UserDetailsService userDetailsService(){
            InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
            manager.createUser(User.withUsername("user").password(new BCryptPasswordEncoder().encode("123")).roles("USER").build());
            manager.createUser(User.withUsername("admin").password(new BCryptPasswordEncoder().encode("123")).roles("ADMIN").build());
            return manager;
        }
    }
    
    
  • 相关阅读:
    颓废ing
    Linux下PF_PACKET的使用(todo)
    TIPC协议(todo)
    TOP命令详解(todo)
    so查找顺序
    把lib打包到so中
    -Bsymbolic: 优先使用本地符号
    GitHub 上最火的 Python 开源项目zz
    __attribute__((weak)) zz
    kmalloc(zz)
  • 原文地址:https://www.cnblogs.com/fly-book/p/12230759.html
Copyright © 2011-2022 走看看