Source code project address

Captcha implementation

About the kaptcha

Kaptcha is a very useful captcha generation tool. With it, you can generate various styles of captchas because it is configurable. Using Kaptcha allows easy configuration:

  • The font of the verification code
  • The size of the captcha font
  • The font color of the verification code font
  • Verification code content range (numbers, letters, Chinese characters!)
  • Captcha image size. Border, border thickness, border color
  • Verification code interference line (can inherit com. Google. Code. Kaptcha. NoiseProducer write a personal definition of interference lines)
  • Captcha styles (fisheye style, 3D, plain blur… Of course also can inherit com. Google. Code. Kaptcha. GimpyEngine define your own style)

Maven rely on

< the dependency > < groupId > com. Making. Penggle < / groupId > < artifactId > kaptcha < / artifactId > < version > 2.3.2 < / version > </dependency>Copy the code

Inject captcha Servlet

** KaptchaConfig.java **

@Component
public class KaptchaConfig {
    @Bean
    public ServletRegistrationBean<KaptchaServlet> kaptchaServlet() {

        ServletRegistrationBean<KaptchaServlet> registrationBean = new ServletRegistrationBean<>(new KaptchaServlet(), "/captcha/kaptcha.jpg"); registrationBean.addInitParameter(Constants.KAPTCHA_SESSION_CONFIG_KEY, Constants.KAPTCHA_SESSION_KEY); / / width registrationBean. AddInitParameter (the KAPTCHA_IMAGE_WIDTH,"140"); / / height registrationBean. AddInitParameter (the KAPTCHA_IMAGE_HEIGHT,"60"); / / font size registrationBean. AddInitParameter (the KAPTCHA_TEXTPRODUCER_FONT_SIZE,"50");
//        registrationBean.addInitParameter(Constants.KAPTCHA_BORDER_THICKNESS,"1"); / / frame / / without borders registrationBean addInitParameter (the KAPTCHA_BORDER,"no"); / / text color registrationBean. AddInitParameter (the KAPTCHA_TEXTPRODUCER_FONT_COLOR,"blue"); / / length registrationBean. AddInitParameter (the KAPTCHA_TEXTPRODUCER_CHAR_LENGTH,"4"); / / character spacing registrationBean. AddInitParameter (the KAPTCHA_TEXTPRODUCER_CHAR_SPACE,"6"); / / you can set a lot of attributes, specific see com. Its code. The kaptcha. Constants / / kaptcha. If there is a border border by defaulttrueWe can set yes ourselves, No // kaptcha.border. Color The border color defaults to color.black // Kaptcha.border. Thickness of the border is 1 by default // kaptcha.producer.impl Verification code generator Defaults to DefaultKaptcha / / kaptcha. Textproducer. Impl captcha text generator defaults to DefaultTextCreator / / kaptcha textproducer. Char. The string Captcha text character content range The default for abcde2345678gfynmnpwx / / kaptcha. Textproducer. Char. The length captcha text character length is 5 / / by default Kaptcha. Textproducer. The font. Names captcha text font style The default for new Font ("Arial", 1, fontSize), new Font("Courier", 1, FontSize) / / kaptcha. Textproducer. The font, size captcha text character size 40 / / kaptcha. Defaults to textproducer. The font, color captcha text characters. The default color for color BLACK / / kaptcha. Textproducer. Char. Space captcha text characters spacing is 2 / / kaptcha. By default, whose. Impl captcha noise generated objects Defaults to DefaultNoise / / kaptcha. Noise. Color Captcha image noise. The default Color for Color BLACK / / kaptcha. Obscurificator. Impl verification code style engine Defaults to WaterRipple / / kaptcha. Word. Impl captcha text rendering Defaults to DefaultWordRenderer / / kaptcha. Background. Impl authentication code generator in the background Defaults to DefaultBackground / / kaptcha. Background. The clear. The from Verification code background color gradually By default Color. LIGHT_GRAY / / kaptcha. Background. Clear. To validate code background Color gradually The default for Color. WHITE / / kaptcha. Image. The width width captcha images The default value is 200 // kaptcha.image.height The default value is 50returnregistrationBean; }}Copy the code

Here we injected a servlet linked to “/captcha/kaptcha.jpg”. Click the Run project to open link. If you see the captcha image, the configuration is successful.

Captcha interceptor

** CaptchaValidateFilter.java **

ublic class CaptchaValidateFilter extends AccessControlFilter {
    private String captchaParam = "captchaCode"; // Verification code submitted by the foreground private String failureKeyAttribute ="shiroLoginFailure"; Public String getCaptchaCode(ServletRequest Request) {returnWebUtils.getCleanParam(request, getCaptchaParam()); } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {// Obtain the correct verification code from session Session = Securityutils.getSubject ().getSession(); String captchaCode = getCaptchaCode(request); String validateCode = (String)session.getAttribute(Constants.KAPTCHA_SESSION_KEY); HttpServletRequest httpServletRequest = WebUtils.toHttp(request); // Check whether the verification code is submitted (allow access)if(!"post".equalsIgnoreCase(httpServletRequest.getMethod())) {  
            return true; } // Return if the verification code is empty or the match failsfalse
	    if(captchaCode == null) {
	    	return false;
	    } else if(validateCode ! = null) { captchaCode = captchaCode.toLowerCase(); validateCode = validateCode.toLowerCase();if(! captchaCode.equals(validateCode)) {return false; }}return true; } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse Response) throws Exception {// If the verification code fails, the storage fails. Key attribute Request. setAttribute(failureKeyAttribute,"Verification code error");  
        return true;  
	}

	public String getCaptchaParam() {
		return captchaParam;
	}

	public void setCaptchaParam(String captchaParam) { this.captchaParam = captchaParam; }}Copy the code

The captcha interceptor inherits AccessControlFilter, which provides basic access control functions, such as whether access is allowed or what to do when access is denied. There are two main methods:

  • IsAccessAllowed: indicates whether access is allowed. MappedValue is the interceptor parameter part of the [urls] configuration that returns true if access is allowed, false otherwise;
  • OnAccessDenied: Indicates whether the access is denied. If true is returned, processing needs to continue. If returning false indicates that the interceptor instance has already been processed, it simply returns

Modify ShiroConfig. Java

public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); // Interceptor. Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>(); / / configuration will not be intercepted the link order of judgment filterChainDefinitionMap. Put ("/css/**"."anon");
        filterChainDefinitionMap.put("/js/**"."anon");
        filterChainDefinitionMap.put("/img/**"."anon");
        filterChainDefinitionMap.put("/layui/**"."anon");
        filterChainDefinitionMap.put("/captcha/**"."anon");
        filterChainDefinitionMap.put("/favicon.ico"."anon"); / / configuration exit filter, of which the specific exit code Shiro has achieved filterChainDefinitionMap for us. The put ("/logout"."logout"); / / <! -- Filter chain definition, executed from top to bottom, usually with /** at the bottom --> this is a pit, if not careful code will not work; / / <! -- authc: All urls must be authenticated to be accessible; Anon: All urls can be accessed anonymously; User "to access the address of the user's authentication through or RememberMe login can - > filterChainDefinitionMap. Put ("/add"."perms[add]");
        filterChainDefinitionMap.put("/login"."captchaVaildate,authc");

        filterChainDefinitionMap.put("/ * *"."user"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); // If this parameter is not set, the system automatically searches for those in the root directory of the Web project"/login.jsp"Page shiroFilterFactoryBean. SetLoginUrl ("/login"); / / to jump after a successful login link shiroFilterFactoryBean setSuccessUrl ("/index"); // Unauthorised interface; shiroFilterFactoryBean.setUnauthorizedUrl("/ 403"); / / custom interceptors Map < String, Filter > filters. = shiroFilterFactoryBean getFilters (); filters.put("captchaVaildate", new CaptchaValidateFilter());
        filters.put("authc", new MyFormAuthenticationFilter());
        return shiroFilterFactoryBean;
    }
Copy the code

Add a captcha interceptor before the form validation interceptor

Remember the login implementation

ShiroConfig configuration

Add the following methods to shiroconfig.java:

public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ...... shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setSecurityManager(securityManager); . } /** * Security manager * @return securityManager
     */
    @Bean
    public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); / / injection remember my manager securityManager. SetRememberMeManager (rememberMeManager ());returnsecurityManager; } /** * cookie object; The rememberMeCookie() method is to set a Cookie generation template, such as the name of the Cookie, how long the Cookie is valid, and so on. * @return rememberMeCookie
     */
    @Bean
    public SimpleCookie rememberMeCookie(){rememberMe SimpleCookie = new SimpleCookie("rememberMe"); / / <! -- Remember that my cookie takes effect in 30 days, in seconds; --> simpleCookie.setMaxAge(30*24*60*60); simpleCookie.setHttpOnly(true);
        returnsimpleCookie; } /** * cookie management object; The rememberMeManager() method is to generate a rememberMe manager and set that rememberMe manager in securityManager * @return rememberMeManager
     */
    @Bean
    public CookieRememberMeManager rememberMeManager(){ CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); / / rememberMe cookie encryption key Suggested that each project is different The default AES algorithm is the key length (128 256 512) cookieRememberMeManager. SetCipherKey (Base64. Decode ("3AvVhmFLUs0KTA3Kprsdag=="));
        returncookieRememberMeManager; }...Copy the code

The login page

<! DOCTYPE html> <html lang="en" class="no-js" xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="utf-8"/> <title> Login -- Layui admin template </title> <link rel="stylesheet" href=".. /.. /layui/css/layui.css" media="all" />

	<link rel="stylesheet" href=".. /css/login.css" media="all" />
</head>
<body>
<div class="login"> <h1>layuiCMS- Admin login </h1> <form class="layui-form" method="post">
		<div class="layui-form-item">
			<input class="layui-input" name="username" placeholder="Username" type="text" autocomplete="off"/>
		</div>
		<div class="layui-form-item">
			<input class="layui-input" name="password" placeholder="Password"  type="password" autocomplete="off"/>
		</div>
		<div class="layui-form-item form_code">
			<input class="layui-input"  name="captchaCode" placeholder="Verification code" lay-verify="required" type="text" autocomplete="off"/>
			<div>
				<img type="image" src=".. /captcha/kaptcha.jpg" id="codeImage" onclick="chageCode()" title="Can't see the picture? Click to retrieve the captcha" style="cursor:pointer;" width="116" height="36"/>
			</div>
		</div>
		<div class="layui-form-item">
			<input type="checkbox" name="rememberMe" title="Remember me." lay-skin="primary"/>
		</div>

		<button class="layui-btn login_btn" lay-submit="" lay-filter="login"</button> </form> </div> <scripttype="text/javascript" src=".. /layui/layui.js"></script>

<script th:inline="javascript">

layui.use(['layer'].function(){
    var layer = layui.layer;
    var message = [[${shiroLoginFailure}]]? [[${shiroLoginFailure}]]:getUrlPara("shiroLoginFailure");
    if(message) { layer.msg(message); }});function getUrlPara(name)
{
    var url = document.location.toString();
    var arrUrl = url.split("?"+name +"=");
    var para = arrUrl[1];
    console.log(para);
    if(para)
    	return decodeURI(para);
}
function chageCode(){
    document.getElementById("codeImage").src=".. /captcha/kaptcha.jpg?"+Math.random();
}

</script>
</body>
</html>
Copy the code