前言:認證在互聯網中會常常見到,其主要做用是安全問題中防止惡意破解、刷票等。在系統開發中認證的實現也有不少種,什麼手機短信認證,郵箱認證等。在這裏我使用最基本的驗證碼的形式進行認證,下面例出過程。html
建立一個簡單的驗證碼生成器,經過流的方式將隨機字體、隨機背景色、干擾線、隨機字符串,夾雜在一塊兒造成驗證碼圖片vue
import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; /** * 自定義驗證碼類 */ public class VerifyCode { private int width = 100; //生成驗證碼圖片的寬度 private int height = 40; //生成驗證碼圖片的高度 private String[] fontNames = {"宋體","楷體","隸書","微軟雅黑"}; private Color bgColor = new Color(255,255,255); //定義驗證碼圖片的背景色 private Random random = new Random(); private String codes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; private String text; //記錄隨機字符串 /** * 獲取隨機一個顏色 * @return */ private Color randomColor(){ int red = random.nextInt(150); int green = random.nextInt(150); int blue = random.nextInt(150); return new Color(red,green,blue); } /** * 獲取隨機一個字體 * @return */ private Font randomFont(){ String name = fontNames[random.nextInt(fontNames.length)]; int style = random.nextInt(4); int size =random.nextInt(5)+24; return new Font(name,style,size); } /** * 獲取隨機一個字符 * @return */ private char randomChar(){ return codes.charAt(random.nextInt(codes.length())); } /** * 建立一個空白的BufferedImage對象 * @return */ private BufferedImage createImage(){ BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D)image.getGraphics(); g2.setColor(bgColor); g2.fillRect(0,0,width,height); return image; } /** * 繪製干擾線 */ private void drawLine(BufferedImage image){ Graphics2D g2 = (Graphics2D) image.getGraphics(); int num = 5; for (int i = 0 ;i < num ; i++){ int x1 = random.nextInt(width); int y1 = random.nextInt(height); int x2 = random.nextInt(width); int y2 = random.nextInt(height); g2.setColor(randomColor()); g2.setStroke(new BasicStroke(1.5f)); g2.drawLine(x1, y1, x2, y2); } } /** * 繪製驗證碼 * @return */ public BufferedImage getImage(){ BufferedImage image = createImage(); Graphics2D g2 = (Graphics2D) image.getGraphics(); StringBuffer sb = new StringBuffer(); for (int i = 0 ; i < 4 ; i++){ String s = randomChar() + ""; sb.append(s); g2.setColor(randomColor()); g2.setFont(randomFont()); float x = i * width * 1.0f / 4; g2.drawString(s,x,height - 15); } this.text = sb.toString(); drawLine(image); return image; } public String getText(){ return text; } /** * 用流傳輸方法 * @return */ public static void output(BufferedImage image, OutputStream out) throws IOException { ImageIO.write(image,"JPEG",out); } }
建立VerifyCode驗證碼生成器實例,將text(隨機字符串)存入session中,將圖片用流的方式傳入前段java
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.awt.image.BufferedImage; import java.io.IOException; @RestController public class VerifyCodeController { @GetMapping("/vercode") public void code(HttpServletRequest req, HttpServletResponse resp) throws IOException { //建立驗證碼生成器實例取得生成圖片和隨機字符串 VerifyCode vc = new VerifyCode(); BufferedImage image = vc.getImage(); String text = vc.getText(); //隨機字符串存入session中 HttpSession session = req.getSession(); session.setAttribute("index_code",text); //用流傳輸 VerifyCode.output(image,resp.getOutputStream()); } }
前段我這裏使用的是vue框架(使用什麼框架不是問題,姑且提一下),img圖片中src路勁調用web
<img src="/vercode" alt="">
啓動服務器,測試,獲取成功
spring
我這裏作登陸認證,表單加入驗證碼輸入安全
<tr> <td> <el-tag>驗證碼</el-tag> </td> <td> <el-input size="mini" v-model="user.code" pleceholder="請輸入驗證碼"></el-input> </td> <td> <img src="/vercode" alt=""> </td> </tr>
這裏只提取驗證碼相關的:服務器
自定義過濾器,繼承GenericFilterBean,重寫doFilter方法session
@Component public class VerifyCodeFilter extends GenericFilterBean { //綁定登陸路徑 private String defaultFilterProcessUrl = "/doLogin"; @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; if ("POST".equalsIgnoreCase(request. getMethod()) && defaultFilterProcessUrl.equals(request.getServletPath())){ String requestCaptcha = request.getParameter("code"); String genCaptcha = (String) request.getSession().getAttribute("index_code"); if(StringUtils.isEmpty(requestCaptcha)){ throw new AuthenticationServiceException("驗證碼不能爲空!"); } if (!genCaptcha.toLowerCase().equals(requestCaptcha.toLowerCase())){ throw new AuthenticationServiceException("驗證碼錯誤!"); } } chain.doFilter(request,response); } }
繼承WebSecurityConfigurerAdapter類,重寫認證方法app
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired VerifyCodeFilter verifyCodeFilter; @Override public void configure(WebSecurity web) throws Exception { //防止驗證圖片被攔截 web.ignoring().antMatchers("/vercode"); } @Override protected void configure(HttpSecurity http) throws Exception { //對前段獲取到的驗證數據進行驗證 http.addFilterBefore(verifyCodeFilter,UsernamePasswordAuthenticationFilter.class); http.authorizeRequests() //省略帳號密碼認證 ... ... ... .permitAll() .and() .csrf().disable() } }
登陸測試 框架
此次就到這裏,有什麼問題或建議能夠在下面評論。