zoukankan      html  css  js  c++  java
  • JavaWeb-SpringSecurity使用短信验证码登陆

      相关博文

      JavaWeb-SpringBoot_一个类实现腾讯云SDK发送短信  传送门

      系列博文

      项目已上传至guthub  传送门

      JavaWeb-SpringSecurity初认识  传送门

      JavaWeb-SpringSecurity在数据库中查询登陆用户  传送门

      JavaWeb-SpringSecurity自定义登陆页面  传送门

      JavaWeb-SpringSecurity实现需求-判断请求是否以html结尾  传送门

      JavaWeb-SpringSecurity自定义登陆配置  传送门

      JavaWeb-SpringSecurity图片验证ImageCode  传送门

      JavaWeb-SpringSecurity记住我功能  传送门

      JavaWeb-SpringSecurity使用短信验证码登陆  传送门

      在项目GaryRESTful.validate.code包下创建SmsCode.java

    package com.Gary.GaryRESTful.validate.code;
    
    import java.time.LocalDateTime;
    
    public class SmsCode {
    
        //发送短信code
        private String code;
        
        //当前系统时间
        private LocalDateTime expireTime;
    
        public SmsCode(String code,int exprieTime)
        {
            this.code = code;
            this.expireTime = LocalDateTime.now().plusSeconds(exprieTime);
        }
        
        public SmsCode(String code,LocalDateTime expireTime)
        {
            this.code = code;
            this.expireTime = expireTime;
        }
        
        //判断当前时间是否存在过期之后
        public boolean isExpired()
        {
    
            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;
        }
        
        
        
    }
    SmsCode.java

      

      优化ImageCode.java与SmsCode.java,将SmsCode.java重命名为ValidateCode.java,并用ImageCode.java继承ValidateCode.java

    package com.Gary.GaryRESTful.validate.code;
    
    import java.time.LocalDateTime;
    
    public class ValidateCode {
    
        //发送短信code
        private String code;
        
        //当前系统时间
        private LocalDateTime expireTime;
    
        public ValidateCode(String code,int expireTime)
        {
            this.code = code;
            this.expireTime = LocalDateTime.now().plusSeconds(expireTime);
        }
        
        public ValidateCode(String code,LocalDateTime expireTime)
        {
            this.code = code;
            this.expireTime = expireTime;
        }
        
        //判断当前时间是否存在过期之后
        public boolean isExpired()
        {
    
            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.java

      导入腾讯云发短信qcloudsms-1.0.5.jar包

      

      ValidateCodeController.java中实现接收发送短信验证码的请求@GetMapping("/code/sms")

        @GetMapping("/code/sms")    
        public void createSmsCode(HttpServletRequest request,HttpServletResponse response) throws ServletRequestBindingException
        {
            //生成短信的校验码
            ValidateCode smsCode = createSmsCode();
            //将我们的校验码放入session域中
            sessionStrategy.setAttribute(new ServletWebRequest(request), sessionSmsKey, smsCode);
            //从request域中获取手机号
            String mobile = ServletRequestUtils.getRequiredStringParameter(request, "mobile");
            //发短信(给mobile手机号发送smsCode验证码)
            sendSms(mobile,smsCode.getCode());
        }
        
        //发短信(给mobile手机号发送smsCode验证码)
        private void sendSms(String mobile, String code) {
            //1.腾讯云自己项目的AppID
            int appid = 1400182502;
            
            String appkey = "58f61b731363faba756087b9504bff46";
    
            int templateId =193928;
            
            String smsSign = "Garyd公众号";
            
            String phoneNumber = mobile;
            
            String[] params = new String[1];
            params[0] = code;
            //将验证码打印出来
            System.out.println("验证码: "+code);
            
            SmsSingleSender sender = new SmsSingleSender(appid,appkey);
            
            //86,手机号,模板id,验证码,smsSign
            try {
                SmsSingleSenderResult result = sender.sendWithParam("86", phoneNumber, templateId, params, smsSign, "", "");
            
                //打印是否发送成功
                System.out.println(result);
            } catch (JSONException | HTTPException | IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    
        //生成短信的校验码
        private ValidateCode createSmsCode() {
            Random r = new Random();
            String code = "" +r.nextInt(10)+r.nextInt(10)+r.nextInt(10)+r.nextInt(10);
            return new ValidateCode(code,120);
        }

      别忘了在SecurityConfig.java中的configure()方法中打开对/code/sms请求的拦截

    //在访问我们的URL时,我们是不需要省份认证,可以立即访问
                .antMatchers("/login.html","/require","/code/image","/code/sms").permitAll()

      测试

      发送验证码请求  localhost:8080/code/sms?mobile=17689470428

      后台result信息输出

      

      【出现result:1031错误表示短信包没钱了!( ╯□╰ )窘迫~】

      当短信发送成功时,result返回值是0,返回值是"OK"

      

      【当控制台输出result第一个参数为 0 后稍等几秒手机便会接收腾讯云发送的短信】

    #datasource
    spring.datasource.url=jdbc:mysql:///springsecurity?serverTimezone=UTC&characterEncoding=utf-8
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.dricer-class-name=com.mysql.jdbc.Driver
    
    #jpa
    #打印出数据库语句
    spring.jpa.show-sql=true
    #更新数据库表
    spring.jpa.hibernate.ddl-auto=update
    
    #配置登陆方式
    gary.security.loginType = JSON
    
    server.port=8080
    
    #验证码长度
    gary.security.code.image.length = 6
    #验证码图片的长
    gary.security.code.image.width = 100
    
    #配置哪些需要我们验证码的Filter
    gary.security.code.image.url = /user,/user/*
    
    #Token过期时间
    gary.security.rememberMeSeconds = 3600
    application.properties
    package com.Gary.GaryRESTful.config;
    
    import javax.sql.DataSource;
    
    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.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
    import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
    
    import com.Gary.GaryRESTful.filter.ValidateCodeFilter;
    import com.Gary.GaryRESTful.handler.LoginFailureHandler;
    import com.Gary.GaryRESTful.handler.LoginSuccessHandler;
    import com.Gary.GaryRESTful.properties.GarySecurityProperties;
    
    
    //Web应用安全适配器
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
    
        //告诉SpringSecurity密码用什么加密的
        @Bean
        public PasswordEncoder passwordEncoder()
        {
            return new BCryptPasswordEncoder();
        }
        
        @Autowired
        private LoginSuccessHandler loginSuccessHandler;
    
        @Autowired
        private LoginFailureHandler loginFailureHandler;
         
        @Autowired
        private GarySecurityProperties garySecurityProperties;
        
        @Autowired    
        private DataSource dataSource;
        
        //负责操作数据库
        public PersistentTokenRepository  persistentTokenRepository()
        {
            JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
            tokenRepository.setDataSource(dataSource);
            return tokenRepository;
        }
        
        @Autowired    
        public UserDetailsService userDetailService;
        
        
        protected void configure(HttpSecurity http) throws Exception{
            
            //声明我们自己写的过滤器
            ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
            //给过滤器赋值
            validateCodeFilter.setAuthenticationFailureHandler(loginFailureHandler);
            validateCodeFilter.setGarySecurityProperties(garySecurityProperties);
            validateCodeFilter.afterPropertiesSet();
            
            //表单验证(身份认证)
            http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                //自定义登陆页面
                .loginPage("/require")
                //如果URL为loginPage,则用SpringSecurity中自带的过滤器去处理该请求
                .loginProcessingUrl("/loginPage")
                //配置登陆成功调用loginSuccessHandler
                .successHandler(loginSuccessHandler)
                //配置登陆失败调用loginFailureHandler
                .failureHandler(loginFailureHandler)
                //记住我功能
                .and()
                .rememberMe()
                //配置persistentTokenRepository
                .tokenRepository(persistentTokenRepository())
                //配置过期秒数
                .tokenValiditySeconds(garySecurityProperties.getRememberMeSeconds())
                //配置userDetailsService
                .userDetailsService(userDetailService)
                .and()
                //请求授权
                .authorizeRequests()
                //在访问我们的URL时,我们是不需要省份认证,可以立即访问
                .antMatchers("/login.html","/require","/code/image","/code/sms").permitAll()
                //所有请求都被拦截,跳转到(/login请求中)
                .anyRequest()
                //都需要我们身份认证
                .authenticated()
                //SpringSecurity保护机制
                .and().csrf().disable();
        }
        
    }
    SecurityConfig.java
    package com.Gary.GaryRESTful.controller;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;
    
    import javax.imageio.ImageIO;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.json.JSONException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.social.connect.web.HttpSessionSessionStrategy;
    import org.springframework.social.connect.web.SessionStrategy;
    import org.springframework.web.bind.ServletRequestBindingException;
    import org.springframework.web.bind.ServletRequestUtils;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.context.request.ServletWebRequest;
    
    import com.Gary.GaryRESTful.properties.GarySecurityProperties;
    import com.Gary.GaryRESTful.validate.code.ImageCode;
    import com.Gary.GaryRESTful.validate.code.ValidateCode;
    import com.github.qcloudsms.SmsSingleSender;
    import com.github.qcloudsms.SmsSingleSenderResult;
    import com.github.qcloudsms.httpclient.HTTPException;
    
    @RestController
    public class ValidateCodeController {
        
        //操作Session
        private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
        
        public static String sessionKey = "session_key_image_code";
    
        public static String sessionSmsKey = "session_key_sms_code";
        
        @Autowired
        private GarySecurityProperties garySecurityProperties;
        
        
        @GetMapping("/code/sms")    
        public void createSmsCode(HttpServletRequest request,HttpServletResponse response) throws ServletRequestBindingException
        {
            //生成短信的校验码
            ValidateCode smsCode = createSmsCode();
            //将我们的校验码放入session域中
            sessionStrategy.setAttribute(new ServletWebRequest(request), sessionSmsKey, smsCode);
            //从request域中获取手机号
            String mobile = ServletRequestUtils.getRequiredStringParameter(request, "mobile");
            //发短信(给mobile手机号发送smsCode验证码)
            sendSms(mobile,smsCode.getCode());
        }
        
        //发短信(给mobile手机号发送smsCode验证码)
        private void sendSms(String mobile, String code) {
            //1.腾讯云自己项目的AppID
            int appid = 1400184301;
            
            String appkey = "58f61b731363faba756087b9504bff46";
            
            //短信正文的id
            int templateId =275243;
            
            String smsSign = "Garyd公众号";
            
            String phoneNumber = mobile;
            
            String[] params = new String[1];
            params[0] = code;
            //将验证码打印出来
            System.out.println("验证码: "+code);
            
            SmsSingleSender sender = new SmsSingleSender(appid,appkey);
            
            //86,手机号,模板id,验证码,smsSign
            try {
                SmsSingleSenderResult result = sender.sendWithParam("86", phoneNumber, templateId, params, smsSign, "", "");
            
                //打印是否发送成功
                System.out.println(result);
            } catch (JSONException | HTTPException | IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    
        //生成短信的校验码
        private ValidateCode createSmsCode() {
            Random r = new Random();
            String code = "" +r.nextInt(10)+r.nextInt(10)+r.nextInt(10)+r.nextInt(10);
            return new ValidateCode(code,120);
        }
    
    
        @GetMapping("/code/image")
        public void createCode(HttpServletRequest request,HttpServletResponse response) throws IOException
        {
            //生成随机数的图片
            ImageCode imageCode = createImageCode(request);
            
            //将随机数放入到session中
            sessionStrategy.setAttribute(new ServletWebRequest(request), sessionKey, imageCode);
            
            //将我们生成的图片写到接口的响应的输出流中
            ImageIO.write(imageCode.getImage(), "JPEG", response.getOutputStream());
            
        }
        
        //生成图片验证码(验证码,图片,失效的时间)
        private ImageCode createImageCode(HttpServletRequest request)
        {
            //定义图片的长和宽
            int width = ServletRequestUtils.getIntParameter(request, "width", garySecurityProperties.getCode().getImage().getWidth());
            int height =  ServletRequestUtils.getIntParameter(request, "height", garySecurityProperties.getCode().getImage().getHeight());;
            
            //生成一张图片
            BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
            
            //获得画笔工具
            Graphics g = image.getGraphics();
            
            //画一个矩形
            g.setColor(new Color(255,255,255));
            g.fillRect(0, 0, width, height);
            
            //画干扰线
            g.setColor(new Color(0,0,0));
            //设置字体
            g.setFont(new Font("Time New Roman",Font.ITALIC,20));
            Random random = new Random();
            
            for(int i=0;i<20;i++)
            {
                int x = random.nextInt(width);
                int y = random.nextInt(height);
                int x1 = random.nextInt(12);
                int y1 = random.nextInt(12);
                //(x,y)到(x+x1,y+y1)
                g.drawLine(x, y, x+x1, y+y1);
            }
            
            //画数据
            String sRand = "";
            for(int i = 0;i<garySecurityProperties.getCode().getImage().getLength();i++)
            {
                String rand =String.valueOf(random.nextInt(10));
                //System.out.println(rand);
                sRand += rand;
                //每一个字都改变一下颜色
                g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
                //画每一个数据
                g.drawString(rand, 13*i, 16);
            }
            
            g.dispose();
            
            //生成我们自己的验证码数据(图片,验证码,过期时间)
            return new ImageCode(image,sRand,garySecurityProperties.getCode().getImage().getExpireIn());
        }
        
        public SessionStrategy getSessionStrategy() {
            return sessionStrategy;
        }
    
        public void setSessionStrategy(SessionStrategy sessionStrategy) {
            this.sessionStrategy = sessionStrategy;
        }
    
        public static String getSessionKey() {
            return sessionKey;
        }
    
        public static void setSessionKey(String sessionKey) {
            ValidateCodeController.sessionKey = sessionKey;
        }
    
    
        
    }
    ValidateCodeController.java

      在GaryRESTful.properties包下创建SmsCodeProperties.java,配置Sms发送短信的配置

    package com.Gary.GaryRESTful.properties;
    
    public class SmsCodeProperties {
    
        private int length = 6;
        private int expireIn = 120;
        private String url;
        
        
        
        public int getLength() {
            return length;
        }
        public void setLength(int length) {
            this.length = length;
        }
        public int getExpireIn() {
            return expireIn;
        }
        public void setExpireIn(int expireIn) {
            this.expireIn = expireIn;
        }
        public String getUrl() {
            return url;
        }
        public void setUrl(String url) {
            this.url = url;
        }
        
        
        
    }
    SmsCodeProperties.java

      优化ImageCodeProperties.java与SmsCodeProperties.java,将ImageCodeProperties.java继承SmsCodeProperties.java,并于少写代码

    package com.Gary.GaryRESTful.properties;
    
    public class ImageCodeProperties extends SmsCodeProperties{
    
        private int width = 67;
        private int height = 23;
        
        public ImageCodeProperties()
        {
            setLength(4);
        }
        
        public int getWidth() {
            return width;
        }
        public void setWidth(int width) {
            this.width = width;
        }
        public int getHeight() {
            return height;
        }
        public void setHeight(int height) {
            this.height = height;
        }
        
        
    }
    ImageCodeProperties.java

      在login.html中添加填写手机验证码<input>,发送验证码的手机号我们给个定值value=17689470428,发送请求时都是通过ajax去进行数据交互,这里直接给个定制,通过<a>标签去访问请求/code/sms?mobile=17689470428(手机号不变)

        <form action="">
        
            手机号:
            <input type="text" name=“mobile” value="17689470428">
            <br>
            短信验证码:
            <input type="text" name="smsCode">
            <a href="/code/sms?mobile=17689470428">发送短信验证码</a>
            
            <input type = "submit">
        </form>

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
    <h1>Gary登陆页面</h1>
        <form action="/loginPage" method="post">
        
            用户名:
            <input type="text" name="username">
            <br>
            
            密码:
            <input type="password" name="password">
            <br>
            
            图片验证码:
            <input type="text" name="imageCode">
            <img src="/code/image">
            <br>
            
            <input name="remember-me" type="checkbox" value="true">
            记住我
            
            <input type="submit">
        
        </form>
        
        <br>
        <hr>
        <br>
        <form action="">
        
            手机号:
            <input type="text" name=“mobile” value="17689470428">
            <br>
            短信验证码:
            <input type="text" name="smsCode">
            <a href="/code/sms?mobile=17689470428">发送短信验证码</a>
            
            <input type = "submit">
        </form>
    
    </body>
    </html>
    login.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
    
    <h1>Gary登陆页面</h1>
        <form action="/loginPage" method="post">
        
            用户名:
            <input type="text" name="username">
            <br>
            
            密码:
            <input type="password" name="password">
            <br>
            
            图片验证码:
            <input type="text" name="imageCode">
            <img src="/code/image">
            <br>
            
            <input name="remember-me" type="checkbox" value="true">
            记住我
            
            <input type="submit">
        
        </form>
        
        <br>
        <hr>
        <br>
        <form action="">
        
            手机号:
            <input type="text" name=“mobile” value="17689470428">
            <br>
            短信验证码:
            <input type="text" name="smsCode">
            <a href="/code/sms?mobile=17689470428">发送短信验证码</a>
            
            <input type = "submit">
        </form>
    
    </body>
    </html>
    login.html
    #datasource
    spring.datasource.url=jdbc:mysql:///springsecurity?serverTimezone=UTC&characterEncoding=utf-8
    spring.datasource.username=root
    spring.datasource.password=123456
    spring.datasource.dricer-class-name=com.mysql.jdbc.Driver
    
    #jpa
    #打印出数据库语句
    spring.jpa.show-sql=true
    #更新数据库表
    spring.jpa.hibernate.ddl-auto=update
    
    #配置登陆方式
    gary.security.loginType = JSON
    
    server.port=8080
    
    #验证码长度
    gary.security.code.image.length = 6
    #验证码图片的长
    gary.security.code.image.width = 100
    
    #配置哪些需要我们验证码的Filter
    gary.security.code.image.url = /user,/user/*
    
    #Token过期时间
    gary.security.rememberMeSeconds = 3600
    application.properties
    package com.Gary.GaryRESTful.config;
    
    import javax.sql.DataSource;
    
    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.core.userdetails.UserDetailsService;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
    import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
    
    import com.Gary.GaryRESTful.filter.ValidateCodeFilter;
    import com.Gary.GaryRESTful.handler.LoginFailureHandler;
    import com.Gary.GaryRESTful.handler.LoginSuccessHandler;
    import com.Gary.GaryRESTful.properties.GarySecurityProperties;
    
    
    //Web应用安全适配器
    @Configuration
    public class SecurityConfig extends WebSecurityConfigurerAdapter{
    
        //告诉SpringSecurity密码用什么加密的
        @Bean
        public PasswordEncoder passwordEncoder()
        {
            return new BCryptPasswordEncoder();
        }
        
        @Autowired
        private LoginSuccessHandler loginSuccessHandler;
    
        @Autowired
        private LoginFailureHandler loginFailureHandler;
         
        @Autowired
        private GarySecurityProperties garySecurityProperties;
        
        @Autowired    
        private DataSource dataSource;
        
        //负责操作数据库
        public PersistentTokenRepository  persistentTokenRepository()
        {
            JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
            tokenRepository.setDataSource(dataSource);
            return tokenRepository;
        }
        
        @Autowired    
        public UserDetailsService userDetailService;
        
        
        protected void configure(HttpSecurity http) throws Exception{
            
            //声明我们自己写的过滤器
            ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
            //给过滤器赋值
            validateCodeFilter.setAuthenticationFailureHandler(loginFailureHandler);
            validateCodeFilter.setGarySecurityProperties(garySecurityProperties);
            validateCodeFilter.afterPropertiesSet();
            
            //表单验证(身份认证)
            http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
                .formLogin()
                //自定义登陆页面
                .loginPage("/require")
                //如果URL为loginPage,则用SpringSecurity中自带的过滤器去处理该请求
                .loginProcessingUrl("/loginPage")
                //配置登陆成功调用loginSuccessHandler
                .successHandler(loginSuccessHandler)
                //配置登陆失败调用loginFailureHandler
                .failureHandler(loginFailureHandler)
                //记住我功能
                .and()
                .rememberMe()
                //配置persistentTokenRepository
                .tokenRepository(persistentTokenRepository())
                //配置过期秒数
                .tokenValiditySeconds(garySecurityProperties.getRememberMeSeconds())
                //配置userDetailsService
                .userDetailsService(userDetailService)
                .and()
                //请求授权
                .authorizeRequests()
                //在访问我们的URL时,我们是不需要省份认证,可以立即访问
                .antMatchers("/login.html","/require","/code/image","/code/sms").permitAll()
                //所有请求都被拦截,跳转到(/login请求中)
                .anyRequest()
                //都需要我们身份认证
                .authenticated()
                //SpringSecurity保护机制
                .and().csrf().disable();
        }
        
    }
    SecurityConfig.java
    package com.Gary.GaryRESTful.controller;
    
    import java.awt.Color;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.util.Random;
    
    import javax.imageio.ImageIO;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.json.JSONException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.social.connect.web.HttpSessionSessionStrategy;
    import org.springframework.social.connect.web.SessionStrategy;
    import org.springframework.web.bind.ServletRequestBindingException;
    import org.springframework.web.bind.ServletRequestUtils;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.context.request.ServletWebRequest;
    
    import com.Gary.GaryRESTful.properties.GarySecurityProperties;
    import com.Gary.GaryRESTful.validate.code.ImageCode;
    import com.Gary.GaryRESTful.validate.code.ValidateCode;
    import com.github.qcloudsms.SmsSingleSender;
    import com.github.qcloudsms.SmsSingleSenderResult;
    import com.github.qcloudsms.httpclient.HTTPException;
    
    @RestController
    public class ValidateCodeController {
        
        //操作Session
        private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
        
        public static String sessionKey = "session_key_image_code";
    
        public static String sessionSmsKey = "session_key_sms_code";
        
        @Autowired
        private GarySecurityProperties garySecurityProperties;
        
        
        @GetMapping("/code/sms")    
        public void createSmsCode(HttpServletRequest request,HttpServletResponse response) throws ServletRequestBindingException
        {
            //生成短信的校验码
            ValidateCode smsCode = createSmsCode();
            //将我们的校验码放入session域中
            sessionStrategy.setAttribute(new ServletWebRequest(request), sessionSmsKey, smsCode);
            //从request域中获取手机号
            String mobile = ServletRequestUtils.getRequiredStringParameter(request, "mobile");
            //发短信(给mobile手机号发送smsCode验证码)
            sendSms(mobile,smsCode.getCode());
        }
        
        //发短信(给mobile手机号发送smsCode验证码)
        private void sendSms(String mobile, String code) {
            //1.腾讯云自己项目的AppID
            int appid = 1400184301;
            
            String appkey = "58f61b731363faba756087b9504bff46";
            
            //短信正文的id
            int templateId =275243;
            
            String smsSign = "Garyd公众号";
            
            String phoneNumber = mobile;
            
            String[] params = new String[1];
            params[0] = code;
            //将验证码打印出来
            System.out.println("验证码: "+code);
            
            SmsSingleSender sender = new SmsSingleSender(appid,appkey);
            
            //86,手机号,模板id,验证码,smsSign
            try {
                SmsSingleSenderResult result = sender.sendWithParam("86", phoneNumber, templateId, params, smsSign, "", "");
            
                //打印是否发送成功
                System.out.println(result);
            } catch (JSONException | HTTPException | IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    
        //生成短信的校验码
        private ValidateCode createSmsCode() {
            Random r = new Random();
            String code = "" ;
            for(int i=0;i<garySecurityProperties.getCode().getSms().getLength();i++)
            {
                code += r.nextInt(10);
            }
            return new ValidateCode(code,garySecurityProperties.getCode().getSms().getExpireIn());
        }
    
    
        @GetMapping("/code/image")
        public void createCode(HttpServletRequest request,HttpServletResponse response) throws IOException
        {
            //生成随机数的图片
            ImageCode imageCode = createImageCode(request);
            
            //将随机数放入到session中
            sessionStrategy.setAttribute(new ServletWebRequest(request), sessionKey, imageCode);
            
            //将我们生成的图片写到接口的响应的输出流中
            ImageIO.write(imageCode.getImage(), "JPEG", response.getOutputStream());
            
        }
        
        //生成图片验证码(验证码,图片,失效的时间)
        private ImageCode createImageCode(HttpServletRequest request)
        {
            //定义图片的长和宽
            int width = ServletRequestUtils.getIntParameter(request, "width", garySecurityProperties.getCode().getImage().getWidth());
            int height =  ServletRequestUtils.getIntParameter(request, "height", garySecurityProperties.getCode().getImage().getHeight());;
            
            //生成一张图片
            BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
            
            //获得画笔工具
            Graphics g = image.getGraphics();
            
            //画一个矩形
            g.setColor(new Color(255,255,255));
            g.fillRect(0, 0, width, height);
            
            //画干扰线
            g.setColor(new Color(0,0,0));
            //设置字体
            g.setFont(new Font("Time New Roman",Font.ITALIC,20));
            Random random = new Random();
            
            for(int i=0;i<20;i++)
            {
                int x = random.nextInt(width);
                int y = random.nextInt(height);
                int x1 = random.nextInt(12);
                int y1 = random.nextInt(12);
                //(x,y)到(x+x1,y+y1)
                g.drawLine(x, y, x+x1, y+y1);
            }
            
            //画数据
            String sRand = "";
            for(int i = 0;i<garySecurityProperties.getCode().getImage().getLength();i++)
            {
                String rand =String.valueOf(random.nextInt(10));
                //System.out.println(rand);
                sRand += rand;
                //每一个字都改变一下颜色
                g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));
                //画每一个数据
                g.drawString(rand, 13*i, 16);
            }
            
            g.dispose();
            
            //生成我们自己的验证码数据(图片,验证码,过期时间)
            return new ImageCode(image,sRand,garySecurityProperties.getCode().getImage().getExpireIn());
        }
        
        public SessionStrategy getSessionStrategy() {
            return sessionStrategy;
        }
    
        public void setSessionStrategy(SessionStrategy sessionStrategy) {
            this.sessionStrategy = sessionStrategy;
        }
    
        public static String getSessionKey() {
            return sessionKey;
        }
    
        public static void setSessionKey(String sessionKey) {
            ValidateCodeController.sessionKey = sessionKey;
        }
    
    
        
    }
    ValidateCodeController.java
    package com.Gary.GaryRESTful.properties;
    
    public class ValidateCodeProperties {
    
        //图片验证码
        private ImageCodeProperties image = new ImageCodeProperties();
    
        private SmsCodeProperties sms = new SmsCodeProperties();
        
        
        
        
        public SmsCodeProperties getSms() {
            return sms;
        }
    
        public void setSms(SmsCodeProperties sms) {
            this.sms = sms;
        }
    
        public ImageCodeProperties getImage() {
            return image;
        }
    
        public void setImage(ImageCodeProperties image) {
            this.image = image;
        }
        
        
        
    }
    ValidateCodeProperties.java
  • 相关阅读:
    20201015-3 每周例行报告
    20201008-1 每周例行报告
    20200924-2 功能测试
    贺敬文2019102936-1总结
    20191114-1 每周例行报告
    20191107-1 每周例行报告
    20191031-1 每周例行报告
    每周例行报告
    20191017-1 每周例行报告
    每周例行报告
  • 原文地址:https://www.cnblogs.com/1138720556Gary/p/11821059.html
Copyright © 2011-2022 走看看