日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

SpringSecurity-短信验证码接口开发

發布時間:2025/3/20 javascript 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SpringSecurity-短信验证码接口开发 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??點擊上方?好好學java?,選擇?星標?公眾號

重磅資訊、干貨,第一時間送達 今日推薦:一個線程池 bug 引發的 GC 思考!個人原創+1博客:點擊前往,查看更多 鏈接:https://segmentfault.com/a/1190000022040383

前言

有時候我們需要有特殊登錄形式,比如說短信驗證碼登錄。他與驗證碼登錄邏輯是不一樣的,所以不能使用Spring Security默認提供的那套邏輯;需要自個去寫一個自定義身份認證邏輯。實現步驟如下:

  • 開發短信驗證碼接口

  • 校驗短信驗證碼并登錄

  • 重構代碼

  • 內容

    1.開發短信驗證碼接口

    ValidateCodeController 我們之前已經寫了圖形驗證碼了,現在我們在此基礎之上重構代碼

    1.1 創建驗證碼實體

    public class ValidateCode {private String code;/*** 過期時間*/private LocalDateTime expireTime;public ValidateCode(String code, int expireIn){this.code=code;/*** 過期時間傳遞的參數應該是一個秒數:根據這個秒數去計算過期時間*/this.expireTime = LocalDateTime.now().plusSeconds(expireIn);}public boolean isExpried() {return LocalDateTime.now().isAfter(expireTime);}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public LocalDateTime getExpireTime() {return expireTime;}public void setExpireTime(LocalDateTime expireTime) {this.expireTime = expireTime;} }

    圖片驗證碼繼承ValidateCode

    public class ImageCode extends ValidateCode{private BufferedImage image;public ImageCode(BufferedImage image,String code,int expireIn){super(code,expireIn);this.image=image;}public BufferedImage getImage() {return image;}public void setImage(BufferedImage image) {this.image = image;} }

    1.2 ValidateCodeGenerator改造

    因為ImageCode繼承ValidateCode,所以我們這個接口返回父類,繼承、面向接口編程。

    public interface ValidateCodeGenerator {/*** 生成驗證碼* @param request* @return*/ValidateCode generate(ServletWebRequest request); }

    1.3 短信發送封裝

    1.定義短信發送接口

    public interface SmsCodeSender {/*** 給某個手機發送短信驗證碼* @param mobile* @param code*/void send(String mobile,String code); }

    2.定義短信接口默認實現類 模擬定義默認接口發送實現類

    public class DefaultSmsCodeSender implements SmsCodeSender {@Overridepublic void send(String mobile, String code) {System.out.println("向手機:"+mobile+" 發送短信驗證碼:"+code);} }

    3.ValidateCodeBeanConfig里面注入

    @Configuration public class ValidateCodeBeanConfig {@Autowiredprivate SecurityProperties securityProperties;/** 這個配置與我們在ImageCodeGenerator上面加一個注解是類似的,但是這樣配置靈活,* 可以添加注解:@ConditionalOnMissingBean 作用是:在初始化這個bean的時候,* 先到spring容器去查找imageCodeGenerator,如果有一個imageCodeGenerator時候,* 就不會再用下面代碼去創建**/@Bean@ConditionalOnMissingBean(name="imageCodeGenerator")public ValidateCodeGenerator imageCodeGenerator(){//方法的名字就是放到Spring容器里bean的名字ImageCodeGenerator imageCodeGenerator = new ImageCodeGenerator();imageCodeGenerator.setSecurityProperties(securityProperties);return imageCodeGenerator;}@Bean@ConditionalOnMissingBean(SmsCodeSender.class)public SmsCodeSender smsCodeSender(){//方法的名字就是放到Spring容器里bean的名字return new DefaultSmsCodeSender();} }

    1.2 ValidateCodeController短信驗證碼生成

    @RestController public class ValidateCodeController {public static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();@Autowiredprivate ValidateCodeGenerator imageCodeGenerator;@Autowiredprivate ValidateCodeGenerator smsCodeGenerator;@Autowiredprivate SmsCodeSender smsCodeSender;@GetMapping("/code/image")public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {/*** 1.根據隨機數生成圖片* 2.將隨機數存到session中* 3.將生成圖片寫到接口的響應中*/ImageCode imageCode = (ImageCode) imageCodeGenerator.generate(new ServletWebRequest(request));sessionStrategy.setAttribute(new ServletWebRequest(request),SESSION_KEY,imageCode);ImageIO.write(imageCode.getImage(),"JPEG",response.getOutputStream());}@GetMapping("/code/sms")public void createSmsCode(HttpServletRequest request, HttpServletResponse response) throws ServletRequestBindingException {/*** 1.根據隨機數生成圖片* 2.將隨機數存到session中* 3.調用短信服務:將短信發送到指定平臺*/ValidateCode smsCode = smsCodeGenerator.generate(new ServletWebRequest(request));sessionStrategy.setAttribute(new ServletWebRequest(request),SESSION_KEY,smsCode);//3.調用短信服務:將短信發送到指定平臺,我們封裝成如下接口:String mobile = ServletRequestUtils.getRequiredStringParameter(request,"mobile");smsCodeSender.send(mobile,smsCode.getCode());} }

    1.3 前端頁面

    <h3>短信登錄</h3> <form action="/authentication/mobile" method="post"><table><tr><td>手機號:</td><td><input type="text" name="mobile" value="13226595347"></td></tr><tr><td>短信驗證碼</td><td><input type="text" name="smsCode"><a href="/code/sms?mobile=13012345678">發送驗證碼</a></td></tr><tr><td colspan="2"><button type="submit">登錄</button></td></tr></table> </form>

    1.4 添加短信驗證碼配置類

    我們抽取短信驗證碼如下屬性SmsCodeProperties:

    public class SmsCodeProperties {private int length = 6;//長度private int expireIn = 60;//過期時間private String url;//要處理的url//getter setter }

    并且圖片驗證碼和其有很大重復部分,我們用繼承關系替代。但是圖片驗證碼默認是4位,而短信驗證碼是6位,如何處理呢?我們在父類默認:length = 6 但是在圖片驗證碼構造器中:setLength(4);ImageCodeProperties:

    public class ImageCodeProperties extends SmsCodeProperties{private int width = 67;private int height = 23;public ImageCodeProperties(){setLength(4);} }

    ValidateCodeProperties配置:

    public class ValidateCodeProperties {private ImageCodeProperties image = new ImageCodeProperties();private SmsCodeProperties sms = new SmsCodeProperties();//getter setter }

    主要可配置的是長度和過期時間 我們在ValidateCodeProperties加一個配置

    1.5 添加短信驗證碼生成器

    短信驗證碼生成器,我們使用@Component("smsCodeGenerator")注解注入到Spring

    圖片驗證碼生成器, @Bean @ConditionalOnMissingBean(name="imageCodeGenerator")注解注入到Spring

    @Component("smsCodeGenerator") public class SmsCodeGenerator implements ValidateCodeGenerator {private SecurityProperties securityProperties;@Overridepublic ValidateCode generate(ServletWebRequest request) {String code = RandomStringUtils.randomNumeric(securityProperties.getCode().getSms().getLength());return new ValidateCode(code,securityProperties.getCode().getSms().getExpireIn());}public SecurityProperties getSecurityProperties() {return securityProperties;}public void setSecurityProperties(SecurityProperties securityProperties) {this.securityProperties = securityProperties;} }

    1.6 生成驗證碼接口:controller

    @RestController public class ValidateCodeController {public static final String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();@Autowiredprivate ValidateCodeGenerator imageCodeGenerator;@Autowiredprivate ValidateCodeGenerator smsCodeGenerator;@Autowiredprivate SmsCodeSender smsCodeSender;@GetMapping("/code/image")public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {/*** 1.根據隨機數生成圖片* 2.將隨機數存到session中* 3.將生成圖片寫到接口的響應中*/ImageCode imageCode = (ImageCode) imageCodeGenerator.generate(new ServletWebRequest(request));sessionStrategy.setAttribute(new ServletWebRequest(request),SESSION_KEY,imageCode);ImageIO.write(imageCode.getImage(),"JPEG",response.getOutputStream());}@GetMapping("/code/sms")public void createSmsCode(HttpServletRequest request, HttpServletResponse response) throws ServletRequestBindingException {/*** 1.根據隨機數生成短信驗證碼* 2.將隨機數存到session中* 3.調用短信服務:將短信發送到指定平臺*/ValidateCode smsCode = smsCodeGenerator.generate(new ServletWebRequest(request));sessionStrategy.setAttribute(new ServletWebRequest(request),SESSION_KEY,smsCode);//3.調用短信服務:將短信發送到指定平臺,我們封裝成如下接口:String mobile = ServletRequestUtils.getRequiredStringParameter(request,"mobile");smsCodeSender.send(mobile,smsCode.getCode());} }

    我們觀察到:生成圖形驗證碼和生成短信驗證碼的邏輯是差不多的,都是3步: 1.生成驗證碼 2.保存驗證碼到session中 3.將驗證碼發送出去(一個是發送到response頁面前端;一個是發送到客戶手機號上面)

    像這種主干邏輯相同,其中個別步驟不一樣的,我們一般會使用“模板方法模式”將其抽象。

    1.7 模板方法模式重構ValidateCodeController中生成驗證碼

    1.7.1 重構完的代碼邏輯如下:
    image.png

    聲明一個ValidateCodeProcessor接口,這個接口有一個抽象的實現: AbstractValidateCodeProcessor(之前短信/圖片驗證碼的流程邏輯會寫到這里面)

    具體的發送是不一樣的:一種是請求返回,一種是調用短信運營商返回。這些不同的地方,會讓其子類去實現。

    注意: 1.ValidateCodeProcessor里面封裝了處理整個驗證碼的生成流程的:包括:a.生成驗證碼 b.存放session c.發送出去

    2.具體的生成邏輯在:ValidateCodeGenerator:他只是封裝了:ValidateCodeProcessor接口的一部分。這也是我們設計思想中分層去封裝。當業務發生變化時候,根據業務發生變化的力度去實現業務邏輯

    1.7.2 AbstractValidateCodeProcessor下generate邏輯
    /***使用依賴查找模式改造* 收集系統中所有的 {@link ValidateCodeGenerator} 接口的實現。*找到之后,把Spring中的bean的名字作為key *然后ValidateCodeGenerator作為value放到map里面去;*目前ValidateCodeGenerator的實現有兩個:圖形驗證碼實現和短信驗證碼實現*/ @Autowired private Map<String, ValidateCodeGenerator> validateCodeGenerators;
    1.7.3 ValidateCodeController
    @RestController public class ValidateCodeController {@Autowiredprivate Map<String, ValidateCodeProcessor> validateCodeProcessors;//將以上2個服務變成一個服務@GetMapping("/code/{type}")public void createCode(@PathVariable String type,HttpServletRequest request, HttpServletResponse response) throws Exception {validateCodeProcessors.get(type+"CodeProcessor").create(new ServletWebRequest(request,response));} }
    1.7.4 WebSecurityConfig

    WebSecurityConfig之前授權是針對:"/code/image"現在變成:"/code/*"

    @Configuration public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate SecurityProperties securityProperties;@Autowiredprivate MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;@Autowiredprivate MyAuthenticationFailureHandler myAuthenticationFailureHandler;@Autowiredprivate UserDetailsService userDetailsService;@Autowiredprivate DataSource dataSource;@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Beanpublic PersistentTokenRepository persistentTokenRepository(){JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();////因為是Jdbc操作,所以我們需要注入數據源:org.springframework.jdbc.core.support.JdbcDaoSupport//tokenRepository繼承org.springframework.jdbc.core.support.JdbcDaoSupporttokenRepository.setDataSource(dataSource);System.out.println("PersistentTokenRepository--dataSource:>dataSource");//tokenRepository.setCreateTableOnStartup(true);//系統啟動的時候創建:CREATE_TABLE_SQL表return tokenRepository;}/*** 定義web安全配置類:覆蓋config方法* 1.參數為HttpSecurity*/@Overrideprotected void configure(HttpSecurity http) throws Exception {/*** 定義了任何請求都需要表單認證*/ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();validateCodeFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);validateCodeFilter.setSecurityProperties(securityProperties);//傳遞securityPropertiesvalidateCodeFilter.afterPropertiesSet();http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)//自定義的額過濾器加到UsernamePasswordAuthenticationFilter前面去.formLogin()//表單登錄---指定了身份認證方式// .loginPage("/login.html").loginPage("/authentication/require").loginProcessingUrl("/authentication/form")//配置UsernamePasswordAuthenticationFilter需要攔截的請求.successHandler(myAuthenticationSuccessHandler)//表單登錄成功之后用自帶的處理器.failureHandler(myAuthenticationFailureHandler)//表單登錄失敗之后用自帶的處理器// http.httpBasic()//http的basic登錄.and().rememberMe().tokenRepository(persistentTokenRepository())//配置remeberMe的token操作.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())//配置token失效秒數.userDetailsService(userDetailsService)//配置操作數據庫用戶的service.and().authorizeRequests()//對請求進行授權.antMatchers("/authentication/require",securityProperties.getBrowser().getLoginPage(),"/code/*").permitAll()//對匹配login.html的請求允許訪問.anyRequest()//任何請求.authenticated().and().csrf().disable();//都需要認證} }

    我們重啟服務試一下:

    image.png

    總結

    以上是生活随笔為你收集整理的SpringSecurity-短信验证码接口开发的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 人妻一区二区在线 | 精品国产视频一区二区三区 | 中文字幕一区二区三区在线视频 | 99精品欧美 | 男人天堂免费视频 | 久久丫精品 | 婷婷六月网 | 狠狠插av| 久久久久久一 | 最近的中文字幕在线看视频 | 香蕉成人av | 欧美精品电影一区二区 | 国产美女主播在线观看 | 18禁免费观看网站 | 校园春色综合 | 总裁边开会边做小娇妻h | 免费观看视频一区二区 | 国产精品自拍合集 | 美女精品在线 | 在线观看一区二区视频 | 免费一级做a爰片久久毛片潮 | 97人人模人人爽人人少妇 | 国产精品一区二区入口九绯色 | 欧美人与动性xxxxx杂性 | 色老久久| 琪琪秋霞午夜被窝电影网 | www毛片com| 成人无码av片在线观看 | 久久久亚洲av波多野结衣 | 亚洲精品尤物 | 青青视频免费 | 国产夫妻自拍av | 欧美黄视频在线观看 | 日韩99| 黑人巨大猛烈捣出白浆 | 西西44rtwww国产精品 | 夜夜爱av | 性工作者十日谈 | 久久伊人精品 | 国产91一区 | 免费黄色高清视频 | 日韩成人欧美 | 三级视频黄色 | 亚洲四区 | 美女脱得一干二净 | 色播激情 | 青青草国产在线视频 | 亚洲熟伦熟女新五十路熟妇 | 久久久久综合 | www.蜜臀| 中文字幕欧美激情 | 重囗味sm一区二区三区 | 中文字幕五码 | 日韩欧美理论 | 天堂资源在线 | 日本韩国视频 | 黄网站视频在线观看 | 后入内射无码人妻一区 | 在线不卡av电影 | 污视频91| 欧美日韩视频网站 | 国内自拍小视频 | 中文字幕亚洲综合 | 亚洲影视精品 | 俺来也在线视频 | 国产精品一区二区三区四区在线观看 | 日韩成年视频 | 精品国产AV色欲天媒传媒 | 国产三极片 | 国产国语性生话播放 | 美女扒开尿口让男人桶 | 麻豆私人影院 | 一区二区三区av夏目彩春 | 这里有精品 | 深夜福利久久 | 337p色噜噜 | 中文在线字幕免费观 | 都市激情校园春色亚洲 | 中文字幕人妻伦伦 | 国产成人无码一区二区三区在线 | 国产美女在线观看 | 天天拍夜夜拍 | www毛片com | 你懂的91| 久草资源 | 欧美日韩视频无码一区二区三 | 人人插人人草 | 青青青青操 | 欧美国产高潮xxxx1819 | 天堂视频免费 | 亚洲一区中文字幕 | 67194少妇在线观看 | 97操 | 日韩欧美在线一区二区 | 国产一级黄色电影 | 激情综合网站 | 特级大胆西西4444人体 | 高清三区 | 天天射日|