1. 程式人生 > >DefaultKaptcha生成驗證碼+伺服器驗證碼亂碼問題

DefaultKaptcha生成驗證碼+伺服器驗證碼亂碼問題

現在很多都是手機簡訊驗證碼,也有需求是圖片驗證碼,很多都是awt和swing來實現 都是手畫比較麻煩 也沒看到有好的工具類來實現   看了一些後 發現一個DefaultKaptcha  goole下面的 還挺好用的 

1.kaptcha相關介紹

   Kaptcha是一個基於SimpleCaptcha的驗證碼開源專案。

2.整合方案

①pom.xml中配置依賴

<!-- 驗證碼-->
<dependency>
  <groupId>com.github.penggle</groupId>
  <artifactId>kaptcha</artifactId>
  <version>2.3.2</version>
</dependency>

②配置驗證碼Kaptcha相關設定

@Configuration
public class kaptchaConfig {
    @Bean(name="captchaProducer")
    public DefaultKaptcha getKaptchaBean(){
        DefaultKaptcha defaultKaptcha=new DefaultKaptcha();
        Properties properties=new Properties();
        properties.setProperty("kaptcha.border", "yes");
        properties.setProperty("kaptcha.border.color", "105,179,90");
        properties.setProperty("kaptcha.textproducer.font.color", "blue");
        properties.setProperty("kaptcha.image.width", "125");
        properties.setProperty("kaptcha.image.height", "45");
        properties.setProperty("kaptcha.session.key", "code");
        properties.setProperty("kaptcha.textproducer.char.length", "4");
        properties.setProperty("kaptcha.textproducer.font.names", "宋體,楷體,微軟雅黑");
        Config config=new Config(properties);
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }
}

或者

在resources下建立myKaptcher.xml檔案

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha">
        <property name="config">
            <bean class="com.google.code.kaptcha.util.Config">
                <constructor-arg type="java.util.Properties">
                    <props>
                        <prop key = "kaptcha.border ">yes</prop>
                        <prop key="kaptcha.border.color">105,179,90</prop>
                        <prop key="kaptcha.textproducer.font.color">blue</prop>
                        <prop key="kaptcha.image.width">100</prop>
                        <prop key="kaptcha.image.height">50</prop>
                        <prop key="kaptcha.textproducer.font.size">27</prop>
                        <prop key="kaptcha.session.key">code</prop>
                        <prop key="kaptcha.textproducer.char.length">4</prop>
                        <prop key="kaptcha.textproducer.font.names">宋體,楷體,微軟雅黑</prop>
                        <prop key="kaptcha.textproducer.char.string">23456789ABCEFGHJKMNOPQRSTUVWXYZ</prop>
                        <prop key="kaptcha.obscurificator.impl">com.google.code.kaptcha.impl.WaterRipple</prop>
                        <prop key="kaptcha.noise.color">black</prop>
                        <prop key="kaptcha.noise.impl">com.google.code.kaptcha.impl.NoNoise</prop>
                        <!--<prop key="kaptcha.noise.impl">com.google.code.kaptcha.impl.DefaultNoise</prop>-->
                        <prop key="kaptcha.background.clear.from">185,56,213</prop>
                        <prop key="kaptcha.background.clear.to">white</prop>
                        <prop key="kaptcha.textproducer.char.space">3</prop>
                    </props>
                </constructor-arg>
            </bean>
        </property>
    </bean>
</beans>

然後在啟動類Application中載入配置

@EnableTransactionManagement// 啟動註解事務管理,等同於xml配置方式的 <tx:annotation-driven />
@SpringBootApplication
@EnableScheduling//啟動註解定時任務
@MapperScan(basePackages = "com.shawn.mapper")
@ImportResource(locations={"classpath:mykaptcha.xml"})
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, args);
    }

}

兩種配置方式在springboot中均可;

③KaptchaController

@CommonsLog
@Controller
public class KaptchaController extends BaseController {
    @Autowired
    private Producer captchaProducer;
    @GetMapping("/getKaptchaImage")
    public void getKaptchaImage() throws Exception {

        response.setDateHeader("Expires", 0);

        // Set standard HTTP/1.1 no-cache headers.
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        // Set IE extended HTTP/1.1 no-cache headers (use addHeader).
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        // Set standard HTTP/1.0 no-cache header.
        response.setHeader("Pragma", "no-cache");
        // return a jpeg
        response.setContentType("image/jpeg");
        // create the text for the image
        String capText = captchaProducer.createText();
        // store the text in the session
        //request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        //將驗證碼存到session
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        log.info(capText);
        // create the image with the text
        BufferedImage bi = captchaProducer.createImage(capText);
        ServletOutputStream out = response.getOutputStream();
        // write the data out
        ImageIO.write(bi, "jpg", out);
        try {
            out.flush();
        } finally {
            out.close();
        }
    }
}

3.測試效果

我用的是魚尾紋效果

Constant 描述 預設值
kaptcha.border 圖片邊框,合法值:yes , no yes
kaptcha.border.color 邊框顏色,合法值: r,g,b (and optional alpha) 或者 white,black,blue. black
kaptcha.border.thickness 邊框厚度,合法值:>0 1
kaptcha.image.width 圖片寬 200
kaptcha.image.height 圖片高 50
kaptcha.producer.impl 圖片實現類 com.google.code.kaptcha.impl.DefaultKaptcha
kaptcha.textproducer.impl 文字實現類 com.google.code.kaptcha.text.impl.DefaultTextCreator
kaptcha.textproducer.char.string 文字集合,驗證碼值從此集合中獲取 abcde2345678gfynmnpwx
kaptcha.textproducer.char.length 驗證碼長度 5
kaptcha.textproducer.font.names 字型 Arial, Courier
kaptcha.textproducer.font.size 字型大小 40px.
kaptcha.textproducer.font.color 字型顏色,合法值: r,g,b  或者 white,black,blue. black
kaptcha.textproducer.char.space 文字間隔 2
kaptcha.noise.impl 干擾實現類 com.google.code.kaptcha.impl.DefaultNoise
kaptcha.noise.color 干擾 顏色,合法值: r,g,b 或者 white,black,blue. black
kaptcha.obscurificator.impl 圖片樣式:  水紋com.google.code.kaptcha.impl.WaterRipple  魚眼com.google.code.kaptcha.impl.FishEyeGimpy 陰影com.google.code.kaptcha.impl.ShadowGimpy com.google.code.kaptcha.impl.WaterRipple
kaptcha.background.impl 背景實現類 com.google.code.kaptcha.impl.DefaultBackground
kaptcha.background.clear.from 背景顏色漸變,開始顏色 light grey
kaptcha.background.clear.to 背景顏色漸變, 結束顏色 white
kaptcha.word.impl 文字渲染器 com.google.code.kaptcha.text.impl.DefaultWordRenderer
kaptcha.session.key session key KAPTCHA_SESSION_KEY
kaptcha.session.date session date KAPTCHA_SESSION_DATE

通常都是用config設定 不會用xml 而且有個問題 在我們生成Base64的時候 

七、注意

生成的Base64編碼前要加入data:image/jpeg;base64,可通過http://imgbase64.duoshitong.com/來判斷生成的Base64圖片是否正確,粘入程式碼,如果正確,會顯示對應圖片,否則生成Base64錯誤。

這個時候我們生成了 本地測試也是能完成 一上傳到伺服器專案上線後就會發現 生成的驗證碼有亂碼

這時候很多人會去設定response的編碼 其實並沒有什麼卵用,因為windos下面字型預設是微軟雅黑伺服器下面字型庫並沒有,

centOS7系統的預設字型為 msam10 ,而且msam1這個字型家族庫在你設定後還是沒法顯示 檢視伺服器字型命令:fc-list

很多資料都去改伺服器字型庫,那只是在一個伺服器下面,多個伺服器呢 不是增加麻煩麼,方案有倆張 一種是自己下載一個字型包放在自己專案裡進行引用,第二種就是下面的最簡單的方式:
@Configuration
public class KaptchaConfig {
//        kaptcha.border  是否有邊框  預設為true  我們可以自己設定yes,no
//        kaptcha.border.color   邊框顏色   預設為Color.BLACK
//        kaptcha.border.thickness  邊框粗細度  預設為1
//        kaptcha.producer.impl   驗證碼生成器  預設為DefaultKaptcha
//        kaptcha.textproducer.impl   驗證碼文字生成器  預設為DefaultTextCreator
//        kaptcha.textproducer.char.string   驗證碼文字字元內容範圍  預設為abcde2345678gfynmnpwx
//        kaptcha.textproducer.char.length   驗證碼文字字元長度  預設為5
//        kaptcha.textproducer.font.names    驗證碼文字字型樣式  預設為new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
//        kaptcha.textproducer.font.size   驗證碼文字字元大小  預設為40
//        kaptcha.textproducer.font.color  驗證碼文字字元顏色  預設為Color.BLACK
//        kaptcha.textproducer.char.space  驗證碼文字字元間距  預設為2
//        kaptcha.noise.impl    驗證碼噪點生成物件  預設為DefaultNoise
//        kaptcha.noise.color   驗證碼噪點顏色   預設為Color.BLACK
//        kaptcha.obscurificator.impl   驗證碼樣式引擎  預設為WaterRipple
//        kaptcha.word.impl   驗證碼文字字元渲染   預設為DefaultWordRenderer
//        kaptcha.background.impl   驗證碼背景生成器   預設為DefaultBackground
//        kaptcha.background.clear.from   驗證碼背景顏色漸進   預設為Color.LIGHT_GRAY
//        kaptcha.background.clear.to   驗證碼背景顏色漸進   預設為Color.WHITE
//        kaptcha.image.width   驗證碼圖片寬度  預設為200
//        kaptcha.image.height  驗證碼圖片高度  預設為50
    @Bean
    public DefaultKaptcha producer() {
        Properties properties = new Properties();
        properties.put("kaptcha.border", "no");
        properties.put("kaptcha.textproducer.font.color", "black");
        properties.put("kaptcha.textproducer.char.space", "10");
        properties.put("kaptcha.textproducer.char.length","4");
        properties.put("kaptcha.image.height","34");
        properties.put("kaptcha.textproducer.font.size","25");
        properties.put("kaptcha.noise.impl","com.google.code.kaptcha.impl.NoNoise");
        properties.put("kaptcha.textproducer.font.names","cmr10");
        properties.put("kaptcha.obscurificator.impl","com.google.code.kaptcha.impl.FishEyeGimpy");
        Config config = new Config(properties);
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        defaultKaptcha.setConfig(config);
        return defaultKaptcha;
    }

}

我試了多次後用了cmr10是可以的。