• SpringBoot整合SpringSecurity实现简单的验证码登陆


    说明

    不知道说啥,就是简单的功能

    创建项目添加依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这时候项目启动的时候就会随机生成用户名密码,并且访问URL的时候会跳转默认登陆页面

    基于内存的认证

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Resource
        VerificationCodeFilter verificationCodeFilter;
    
        @Bean
        PasswordEncoder passwordEncoder() {
            return NoOpPasswordEncoder.getInstance();
        }
    
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication() // 自定义内存中的帐号密码
                    .withUser("username")
                    .password("password")
                    .roles("admin"); // 定义账号的角色
        }
    
        @Override
        public void configure(WebSecurity web) throws Exception {
        	// 定义一些资源相关的URL不用被拦截
            web.ignoring().antMatchers("/css/**", "/js/**", "/index.html", "/images/**", "/fonts/**", "/favicon.ico", "/verifyCode");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
        	// 在账号密码验证之前验证验证码
            http.addFilterBefore(verificationCodeFilter, UsernamePasswordAuthenticationFilter.class);
            // 设置请求鉴定
            http.authorizeRequests()
                    .antMatchers("/backstage/**").hasRole("admin") // 设置需要拦截的请求
                    .and()
                    .formLogin()
                    .loginPage("/backstage/login") // 设置默认登陆页面
                    .loginProcessingUrl("/backstage/doLogin") // 设置登录页面表单的post请求url
                    .defaultSuccessUrl("/backstage/") // 设置登陆成功后默认跳转url
                    .permitAll()
                    .and().csrf().disable(); // 关闭csrf
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    添加验证码依赖

    <dependency>
        <groupId>com.github.axet</groupId>
        <artifactId>kaptcha</artifactId>
        <version>0.0.9</version>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    创建验证码过滤器

    @Component
    public class VerificationCodeFilter extends GenericFilter {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
                             FilterChain filterChain) throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) servletRequest;
            HttpServletResponse resp = (HttpServletResponse) servletResponse;
            if (HttpMethod.POST.name().equals(req.getMethod()) && "/backstage/doLogin".equals(req.getServletPath())) {
                String code = req.getParameter("captcha");
                String verifyCode = (String) req.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
                if (code == null || StringUtils.isEmpty(code) || !code.toLowerCase().equals(verifyCode.toLowerCase())) {
                    resp.setContentType("application/json;charset=utf-8");
                    PrintWriter out = resp.getWriter();
                    out.write(new ObjectMapper().writeValueAsString(HttpResult.error("ErrorVerifyCode")));
                    out.flush();
                    out.close();
                } else {
                    filterChain.doFilter(req, resp);
                }
            } else {
                filterChain.doFilter(req, resp);
            }
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    HTTP结果封装

    public class HttpResult {
    
    	private int code = 200;
    	private String msg;
    	private Object data;
    	
    	public static HttpResult error() {
    		return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, "未知异常,请联系管理员");
    	}
    	
    	public static HttpResult error(String msg) {
    		return error(HttpStatus.SC_INTERNAL_SERVER_ERROR, msg);
    	}
    	
    	public static HttpResult error(int code, String msg) {
    		HttpResult r = new HttpResult();
    		r.setCode(code);
    		r.setMsg(msg);
    		return r;
    	}
    
    	public static HttpResult ok(String msg) {
    		HttpResult r = new HttpResult();
    		r.setMsg(msg);
    		return r;
    	}
    	
    	public static HttpResult ok(Object data) {
    		HttpResult r = new HttpResult();
    		r.setData(data);
    		return r;
    	}
    	
    	public static HttpResult ok() {
    		return new HttpResult();
    	}
    
    	public int getCode() {
    		return code;
    	}
    
    	public void setCode(int code) {
    		this.code = code;
    	}
    
    	public String getMsg() {
    		return msg;
    	}
    
    	public void setMsg(String msg) {
    		this.msg = msg;
    	}
    
    	public Object getData() {
    		return data;
    	}
    
    	public void setData(Object data) {
    		this.data = data;
    	}
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    验证码生成接口

    @RestController("/backstage")
    public class SysLoginController {
    
    	@Autowired
    	private Producer producer;
    //	@Autowired
    //	private SysUserService sysUserService;
    //	@Autowired
    //	private AuthenticationManager authenticationManager;
    
    
    
    	@GetMapping("/captcha.jpg")
    	public void captcha(HttpServletResponse response, HttpServletRequest request) throws ServletException, IOException {
    		response.setHeader("Cache-Control", "no-store, no-cache");
    		response.setContentType("image/jpeg");
    
    		// 生成文字验证码
    		String text = producer.createText();
    		// 生成图片验证码
    		BufferedImage image = producer.createImage(text);
    		// 保存到验证码到 session
    		request.getSession().setAttribute(Constants.KAPTCHA_SESSION_KEY, text);
    
    		ServletOutputStream out = response.getOutputStream();
    		ImageIO.write(image, "jpg", out);	
    		IOUtils.closeQuietly(out);
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    登录页面

    <!DOCTYPE html>
    <html xmlns:th="http://www.w3.org/1999/xhtml">
    <head>
        <!-- Standard Meta -->
        <meta charset="utf-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
    
        <!-- Site Properties -->
        <title>Login Example - Semantic</title>
        <link rel="stylesheet" href="../../static/lib/editormd/css/editormd.min.css"
              th:href="@{/lib/editormd/css/editormd.min.css}">
        <link rel="stylesheet" href="../../static/css/icon.min.css" th:href="@{/css/icon.min.css}">
        <link rel="stylesheet" href="../../static/css/semantic.min.css" th:href="@{/css/semantic.min.css}">
        <link rel="stylesheet" href="../../static/css/typo.css" th:href="@{/css/typo.css}">
        <link rel="stylesheet" href="../../static/css/animate.css" th:href="@{/css/animate.css}">
        <link rel="stylesheet" href="../../static/lib/prism/prism.css" th:href="@{/lib/prism/prism.css}">
        <link rel="stylesheet" href="../../static/lib/tocbot/tocbot.css" th:href="@{/lib/tocbot/tocbot.css}">
        <link rel="stylesheet" href="../../static/css/me.css" th:href="@{/css/me.css}">
        <link rel="stylesheet" href="../../static/css/blog.css" th:href="@{/css/blog.css}">
        <link rel="stylesheet" href="../../static/css/common.css" th:href="@{/css/common.css}">
        <link rel="stylesheet" href="../../static/css/action.css" th:href="@{/css/action.css}">
        <link rel="stylesheet" type="text/css" href="../../static/css/font-awesome.min.css"
              th:href="@{/css/font-awesome.min.css}"/>
        <link rel="stylesheet" href="../../static/css/color.css" th:href="@{/css/color.css}"/>
    
        <style type="text/css">
            body {
                background-color: #DADADA;
            }
            body > .grid {
                height: 100%;
            }
            .image {
                margin-top: -100px;
            }
            .column {
                max-width: 450px;
            }
        </style>
        <script>
            $(document)
                .ready(function() {
                    $('.ui.form')
                        .form({
                            fields: {
                                email: {
                                    identifier  : 'email',
                                    rules: [
                                        {
                                            type   : 'empty',
                                            prompt : 'Please enter your e-mail'
                                        },
                                        {
                                            type   : 'email',
                                            prompt : 'Please enter a valid e-mail'
                                        }
                                    ]
                                },
                                password: {
                                    identifier  : 'password',
                                    rules: [
                                        {
                                            type   : 'empty',
                                            prompt : 'Please enter your password'
                                        },
                                        {
                                            type   : 'length[6]',
                                            prompt : 'Your password must be at least 6 characters'
                                        }
                                    ]
                                }
                            }
                        })
                    ;
                })
            ;
        </script>
    </head>
    <body>
    
    <div class="ui middle aligned center aligned grid">
        <div class="column">
            <h2 class="ui teal header">
                <div class="content">
                    Log-in to your account
                </div>
            </h2>
            <form id="loginForm" class="ui large form" method="post"
                  th:action="@{/backstage/doLogin}"
                  action="/backstage/login">
                <div class="ui stacked segment">
                    <div class="field">
                        <div class="ui left icon input">
                            <i class="user icon"></i>
                            <input type="text" name="username" placeholder="E-mail address">
                        </div>
                    </div>
                    <div class="field">
                        <div class="ui left icon input">
                            <i class="lock icon"></i>
                            <input type="password" name="password" placeholder="Password">
                        </div>
                    </div>
                    <div class="two fields">
                        <div class="field">
                            <div class="ui left icon input">
                                <i class="lock icon"></i>
                                <input type="text" name="captcha" placeholder="验证码">
                            </div>
                        </div>
                        <div class="ui field">
                            <img src="#" th:src="@{/captcha.jpg}"/>
                        </div>
                    </div>
    <!--                <div class="ui fluid large teal submit button"-->
    <!--                     οnclick="function submitLoginForm() {-->
    <!--                         $('#loginForm').submit();-->
    <!--                 } submitLoginForm()">Login</div>-->
                    <input class="ui fluid large teal submit button" type="submit" value="Login"/>
                </div>
    
                <div class="ui error message"></div>
    
            </form>
    
        </div>
    </div>
    
    <script>
    
    </script>
    
    </body>
    
    </html>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
  • 相关阅读:
    第八章、ansible基于清单管理大项目
    修改angular cli 的默认包管理器
    小啊呜产品读书笔记001:《邱岳的产品手记-06》第13讲 无用却必要:产品规划【上】 & 第14讲 留白与节奏:产品规划【下】
    ArcGIS中ArcMap为不含坐标系的图层添加地理坐标系或投影坐标系
    Docker 中常用的命令
    【python】可视化
    创新案例|Amazon.com 2023 年营销策略:电子商务零售巨头商业案例研究
    C和指针 第10章 结构和联合 10.1 结构基础知识
    北大肖臻老师《区块链技术与应用》系列课程学习笔记[27]以太坊-反思
    汇编指令转机器码
  • 原文地址:https://blog.csdn.net/FZUMRWANG/article/details/125628866