企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
1. 依赖管理 ```xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.6.RELEASE</version> <relativePath/> </parent> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> ``` 2. 配置文件`application.yml` ```yaml server: port: 80 ``` 3. 登录页`resources/static/login.html` ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>登录</title> </head> <body> <form action="/login" method="post"> <div> <h3>账户登录</h3> <input type="text" placeholder="用户名" name="username" required="required"/> <input type="password" placeholder="密码" name="password" required="required"/><br> <input type="text" name="imageCode" placeholder="验证码"/> <img src="/code/image"/> <button type="submit">登录</button> </div> </form> </body> </html> ``` 4. 启动类 ```java @SpringBootApplication public class SpringSecurityApplication { public static void main(String[] args) { SpringApplication.run(SpringSecurityApplication.class, args); } } ``` 5. 控制器 - 主页(可作为资源) ```java @RestController public class HomeController { @GetMapping("/") public String home() { return "hello spring security"; } } ``` - 获取验证码图片(暂时存储在session中) ```java @RestController public class ValidateController { public final static String SESSION_KEY = "SESSION_KEY_IMAGE_CODE"; @GetMapping("/code/image") public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException { // 生成随机码 String code = createCode(4); // TODO 将随机码存储起来(为了方便起见,暂时存储在session中,也可存在关系型或非关系型数据库中) request.getSession().setAttribute(SESSION_KEY, code); // 将图片传给用户 ImageIO.write(createImageCode(70, 20, code), "jpeg", response.getOutputStream()); } /** * 生成一个随机码图片 * * @param width 随机码图片宽度 * @param height 随机码图片高度 * @param code 随机码 * @return 随机码图片 */ private BufferedImage createImageCode(int width, int height, String code) { // 图形实例 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 图形属性 Graphics g = image.getGraphics(); g.setColor(getRandomColor(200, 250)); g.fillRect(0, 0, width, height); g.setFont(new Font("Times New Roman", Font.ITALIC, 20)); g.setColor(getRandomColor(160, 200)); // 随机器 Random random = new Random(); // 干扰线 for (int i = 0; i < 155; i++) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x, y, x + xl, y + yl); } // 绘制随机码 for (int i = 0; i < code.length(); i++) { g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110))); g.drawString(code.substring(i, i + 1), 13 * i + 6, 16); } g.dispose(); return image; } /** * 生成一个随机码 * * @param length 随机码位数 * @return 随机码 */ private String createCode(int length) { Random random = new Random(); StringBuilder code = new StringBuilder(); for (int i = 0; i < length; i++) { code.append(random.nextInt(10)); } return code.toString(); } /** * 获取一种随机的颜色 */ private Color getRandomColor(int fc, int bc) { Random random = new Random(); if (fc > 255) { fc = 255; } if (bc > 255) { bc = 255; } int r = fc + random.nextInt(bc - fc); int g = fc + random.nextInt(bc - fc); int b = fc + random.nextInt(bc - fc); return new Color(r, g, b); } } ``` 6. 自定义认证`MyUserDetailsService` ```java @Service public class MyUserDetailsService implements UserDetailsService { private final PasswordEncoder passwordEncoder; public MyUserDetailsService(PasswordEncoder passwordEncoder) { this.passwordEncoder = passwordEncoder; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { return new User("user", passwordEncoder.encode("user"), Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"))); } } ``` > 添加了一个用户:`user`,密码:`user`。 7. 自定义验证码异常类`ValidateCodeException` ```java public class ValidateCodeException extends AuthenticationException { private static final long serialVersionUID = 5022575393500654458L; ValidateCodeException(String message) { super(message); } } ``` > 继承`AuthenticationException`,框架识别的异常类。 8. 验证码过滤器(暂时存储在session中,在session中验证) ```java @Component public class ValidateCodeFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if ("/login".equalsIgnoreCase(request.getRequestURI()) && "post".equalsIgnoreCase(request.getMethod())) { try { validateCode(request); } catch (ValidateCodeException exception) { response.getWriter().write(exception.getMessage()); return; } } filterChain.doFilter(request, response); } /** * 验证Code */ private void validateCode(HttpServletRequest request) { String imageCode = request.getParameter("imageCode"); String sessionCode = (String) request.getSession().getAttribute(ValidateController.SESSION_KEY); if (StringUtils.isEmpty(imageCode)) { throw new ValidateCodeException("code can't be null!"); } if (StringUtils.isEmpty(sessionCode)) { throw new ValidateCodeException("code isn't exist!"); } if (!imageCode.equalsIgnoreCase(sessionCode)) { throw new ValidateCodeException("code is error!"); } request.getSession().removeAttribute("imageCode"); } } ``` 9. 完成配置类,组装配置`BrowserSecurityConfig` ```java @Configuration public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { private static final String[] WHITE_LIST = new String[]{"/login.html", "/code/image"}; @Autowired private ValidateCodeFilter validateCodeFilter; @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class); http.formLogin() .loginPage("/login.html").loginProcessingUrl("/login"); http.authorizeRequests() .antMatchers(WHITE_LIST).permitAll() .anyRequest() .authenticated(); http.csrf() .disable(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } ``` 10. 访问http://www.zhangpn.com/进行验证。