首页>>后端>>Spring->SpringSecurity 添加验证码的两种方式

SpringSecurity 添加验证码的两种方式

时间:2023-11-29 本站 点击:0

SpringSecurity 添加验证码的两种方式

方式一:自定义认证逻辑

生成验证码工具

<dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version></dependency>

添加Kaptcha配置

@ConfigurationpublicclassKaptchaConfig{@BeanProducerkaptcha(){Propertiesproperties=newProperties();properties.setProperty("kaptcha.image.width","150");properties.setProperty("kaptcha.image.height","50");properties.setProperty("kaptcha.textproducer.char.string","0123456789");properties.setProperty("kaptcha.textproducer.char.length","4");Configconfig=newConfig(properties);DefaultKaptchadefaultKaptcha=newDefaultKaptcha();defaultKaptcha.setConfig(config);returndefaultKaptcha;}}

生成验证码文本,放入HttpSession中

根据验证码文本生成图片 通过IO流写出到前端。

@RestControllerpublicclassLoginController{@AutowiredProducerproducer;@GetMapping("/vc.jpg")publicvoidgetVerifyCode(HttpServletResponseresp,HttpSessionsession)throwsIOException{resp.setContentType("image/jpeg");Stringtext=producer.createText();session.setAttribute("kaptcha",text);BufferedImageimage=producer.createImage(text);try(ServletOutputStreamout=resp.getOutputStream()){ImageIO.write(image,"jpg",out);}}@RequestMapping("/index")publicStringindex(){return"loginsuccess";}@RequestMapping("/hello")publicStringhello(){return"hellospringsecurity";}}

form表单

<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>登录</title><linkhref="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css"rel="stylesheet"id="bootstrap-css"><scriptsrc="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script><scriptsrc="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script></head><style>#login.container#login-row#login-column#login-box{border:1pxsolid#9C9C9C;background-color:#EAEAEA;}</style><body><divid="login"><divclass="container"><divid="login-row"class="rowjustify-content-centeralign-items-center"><divid="login-column"class="col-md-6"><divid="login-box"class="col-md-12"><formid="login-form"class="form"action="/doLogin"method="post"><h3class="text-centertext-info">登录</h3><divth:text="${SPRING_SECURITY_LAST_EXCEPTION}"></div><divclass="form-group"><labelfor="username"class="text-info">用户名:</label><br><inputtype="text"name="uname"id="username"class="form-control"></div><divclass="form-group"><labelfor="password"class="text-info">密码:</label><br><inputtype="text"name="passwd"id="password"class="form-control"></div><divclass="form-group"><labelfor="kaptcha"class="text-info">验证码:</label><br><inputtype="text"name="kaptcha"id="kaptcha"class="form-control"><imgsrc="/vc.jpg"alt=""></div><divclass="form-group"><inputtype="submit"name="submit"class="btnbtn-infobtn-md"value="登录"></div></form></div></div></div></div></div></body>

验证码图片地址为我们在Controller中定义的验证码接口地址。

身份认证是AuthenticationProvider的authenticate方法完成,因此验证码可以在此之前完成:

publicclassKaptchaAuthenticationProviderextendsDaoAuthenticationProvider{@OverridepublicAuthenticationauthenticate(Authenticationauthentication)throwsAuthenticationException{HttpServletRequestreq=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();Stringkaptcha=req.getParameter("kaptcha");StringsessionKaptcha=(String)req.getSession().getAttribute("kaptcha");if(kaptcha!=null&&sessionKaptcha!=null&&kaptcha.equalsIgnoreCase(sessionKaptcha)){returnsuper.authenticate(authentication);}thrownewAuthenticationServiceException("验证码输入错误");}}

配置AuthenticationManager:

@ConfigurationpublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@BeanAuthenticationProviderkaptchaAuthenticationProvider(){InMemoryUserDetailsManagerusers=newInMemoryUserDetailsManager(User.builder().username("xiepanapn").password("{noop}123").roles("admin").build());KaptchaAuthenticationProviderprovider=newKaptchaAuthenticationProvider();provider.setUserDetailsService(users);returnprovider;}@Override@BeanpublicAuthenticationManagerauthenticationManagerBean()throwsException{ProviderManagermanager=newProviderManager(kaptchaAuthenticationProvider());returnmanager;}@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{http.authorizeRequests().antMatchers("/vc.jpg").permitAll().anyRequest().authenticated().and().formLogin().loginPage("/mylogin.html").loginProcessingUrl("/doLogin").defaultSuccessUrl("/index.html").failureForwardUrl("/mylogin.html").usernameParameter("uname").passwordParameter("passwd").permitAll().and().csrf().disable();}}

配置UserDetailsService提供的数据源

提供AuthenticationProvider实例并配置UserDetailsService

重写authenticationManagerBean方法提供一个自己的ProviderManager并自定义AuthenticationManager实例。

方式二:自定义过滤器

LoginFilter继承UsernamePasswordAuthenticationFilter 重写attemptAuthentication方法:

publicclassLoginFilterextendsUsernamePasswordAuthenticationFilter{@OverridepublicAuthenticationattemptAuthentication(HttpServletRequestrequest,HttpServletResponseresponse)throwsAuthenticationException{if(!request.getMethod().equals("POST")){thrownewAuthenticationServiceException("Authenticationmethodnotsupported:"+request.getMethod());}Stringkaptcha=request.getParameter("kaptcha");StringsessionKaptcha=(String)request.getSession().getAttribute("kaptcha");if(!StringUtils.isEmpty(kaptcha)&&!StringUtils.isEmpty(sessionKaptcha)&&kaptcha.equalsIgnoreCase(sessionKaptcha)){returnsuper.attemptAuthentication(request,response);}thrownewAuthenticationServiceException("验证码输入错误");}}

在SecurityConfig中配置LoginFilter

@ConfigurationpublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth.inMemoryAuthentication().withUser("javaboy").password("{noop}123").roles("admin");}@Override@BeanpublicAuthenticationManagerauthenticationManagerBean()throwsException{returnsuper.authenticationManagerBean();}@BeanLoginFilterloginFilter()throwsException{LoginFilterloginFilter=newLoginFilter();loginFilter.setFilterProcessesUrl("/doLogin");loginFilter.setAuthenticationManager(authenticationManagerBean());loginFilter.setAuthenticationSuccessHandler(newSimpleUrlAuthenticationSuccessHandler("/hello"));loginFilter.setAuthenticationFailureHandler(newSimpleUrlAuthenticationFailureHandler("/mylogin.html"));returnloginFilter;}@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{http.authorizeRequests().antMatchers("/vc.jpg").permitAll().anyRequest().authenticated().and().formLogin().loginPage("/mylogin.html").permitAll().and().csrf().disable();http.addFilterAt(loginFilter(),UsernamePasswordAuthenticationFilter.class);}}

显然第二种比较简单。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/Spring/325.html