認證:登錄和認證是 兩個概念,比如你兩周、一個月,可能只登錄了一次,但認證卻是每次訪問都要經過的步驟。
對於圖中的認證不成功,也要繼續處理,這個我覺得得看業務,比如管理系統,不登錄就不讓你訪問,但對於比如電商的商品信息,不登錄,也是可以訪問的。
一、寫一個用戶注冊服務
數據庫user表:
User類:
單一職責原則:用戶注冊服務,得新建一個UserInfo類,用來接收前端傳過來的注冊用戶信息,而最好不要使用User類直接接收。
新增方法,可以將UserInfo返回,前端可以做相應的展示。
Controller:
Service:
PostMan調用,成功。
二、HttpBasic認證
在HTTP協議進行通信的過程中,HTTP協議定義了基本認證過程以允許HTTP服務器對WEB瀏覽器進行用戶身份證的方法,當一個客戶端向HTTP服務器進行數據請求時,如果客戶端未被認證,則HTTP服務器將通過基本認證過程對客戶端的用戶名及密碼進行驗證,以決定用戶是否合法。
具體做法是,將用戶名、密碼用:號隔開,然后base64編碼,放在請求頭的Authorization字段里,值是Basic base64編碼的字符串
RequestHeader
Authorization:Basic Base64(用戶名:密碼)
比較簡單,但是安全性不高。
下面寫一個HttpBasic過濾器,做認證
package com.nb.security.filter; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.nb.security.entity.User; import com.nb.security.service.IUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.Base64Utils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * 處理httpbasic認證過濾器 * httpbasic:請求頭,即Authorization:Basic 加密字符串 * 加密字符串為Base64編碼的用戶名:密碼字符串 * Authorization Basic bGh5OmxoeWFwcA== * 在SpringBoot里,任何實現了Filter接口的類,SpringBoot會自動把它加到web應用的過濾器鏈里,只要聲名為Component就行了 */ //@Order(2) @Component public class BasicAuthorizationFilter extends OncePerRequestFilter {//確保在一次請求只通過一次filter,並不是所有的container都像我們期望的只過濾一次,servlet版本不同,表現也不同 @Autowired private IUserService userService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { System.err.println("++++認證++++"); String authHeader = request.getHeader("Authorization"); if (StringUtils.isNotBlank(authHeader)) { String token64 = StringUtils.substringAfter(authHeader, "Basic "); String token = new String(Base64Utils.decodeFromString(token64));//base64解碼 String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(token, ":");//分隔用戶名和密碼 String username = items[0]; String password = items[1]; User user = userService.getOne(new QueryWrapper<User>().eq("username", username)); if (user != null && StringUtils.equals(user.getPassword(), password)) { //將用戶信息放到request request.setAttribute("user", user); } } //繼續執行其他過濾器 filterChain.doFilter(request, response); } }
Controller:
Postman訪問,在請求頭輸入數據庫已存在的username、password:
錯誤的訪問
httpbasic至此完成,問題:不能每個請求都帶上用戶名密碼吧?
+++++++++++++++++++++++++++++分割線++++++++++++++++++++++++++++++
小結
本篇說了 httpbasic過濾器進行HTTPBasic認證
代碼:https://github.com/lhy1234/springcloud-security/tree/master/nb-user-api