Spring cloud微服務安全實戰-3-11API安全機制之登錄





流控、認證、審計、授權以上都做了初步的簡單的實現。


之前寫的代碼,base64加密了用戶名和密碼。
缺點1:每次請求都要帶用戶名密碼 增加了泄露的風險。


每次傳上來用戶名和密碼都要check驗證。check是個非常耗資源的事


基於token的身份認證



token是有實效的


對於java開發,最常見的實現

代碼實現來驗證請求的流程

userController內增加login登陸的方法。


 @GetMapping("/login")
    public void login(@Validated UserInfo user,HttpServletRequest request){
        UserInfo info = userService.login(user);
        request.getSession().setAttribute("user",user);
    }

 

 

userService內增加login方法

UserInfo login(UserInfo user);

 

實現類實現login的方法

 @Override
    public UserInfo login(UserInfo info) {
        UserInfo result=null;
        User user=userRepository.findByUsername(info.getUsername());
        if(user!=null && SCryptUtil.check(info.getPassword(),user.getPassword())){
            result=user.buildInfo();
        }
        return result;
    }

 



因為之前做的授權的攔截器,把所有的請求都給攔截了。修改登陸時候我們不需要攔截,

定義一個數組,把不需要攔截的url放在數組內。

請求的路徑如果不在我們的數組內就執行原來訪問控制的邏輯。

如果是登陸的路徑的話,不判斷Attribute是否存在user了,也不判斷請求的方法是否有權限了。直接返回true

private String[] permitUrls=new String[] {"/users/login"};
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(4);
        boolean result=true;
        if(!ArrayUtils.contains(permitUrls,request.getRequestURI())){
            User user=(User)request.getAttribute("user");
            if (user==null){
                response.setContentType("text/plain");
                response.getWriter().write("need authentication");
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
                return false;
            }else{
                String method = request.getMethod();
                if(!user.hasPermission(method)){
                    response.setContentType("text/plain");
                    response.getWriter().write("forbidden");
                    response.setStatus(HttpStatus.FORBIDDEN.value());
                    return false;
                }
            }
        }


        return result;
    }

 




啟動服務進行測試

先調用獲取用戶信息的服務,返回了401,沒有帶身份認證信息。

http://localhost:8080/users/13

下面來調用一下login的方法,傳入用戶名和密碼

這個方法返回了200.里面的Reponse Headers里面。Set-Cookies里面寫的JSESSIONID

類似於下面這種:

Set-Cookie:
JSESSIONID=A0C5DF8537D2E42D9542774AB18EBCDF; Path=/; HttpOnly



在chrome的設置里面








這就是我們存起來的 服務器返回的token

session有了信息了 再去訪問

我們可以看發出去的請求里面 Cookie里面有JSessionID,剛才瀏覽器里面存的JSessionID就從這里發出去了。

也就是這里的第四部,第五步

以上就是session的原理。你要明白的是,基於cookie、session的本質上仍然還是基於token的認證方式。只不過他的這種認證方式是servlet規范里面已經都實現好了的。有優點也有缺點,客戶端只存一個串,真的信息是存在服務器端的,另外一個優點就是使用起來很方便,因為所有的東西servlet容器都替你實現好了,你啥都不用管了,代碼里只需要getSession()然后往里面放東西就可以了。驗證的時候只需要從里面拿,然后驗證就可以了。使用起來非常的方便
缺點:只針對瀏覽器起作用,因為我返回的Repoonse Header,瀏覽器收到這個Repoonse Header然后自個去設置cookie這件事只有瀏覽器支持。如果你是一個客戶或者app 甚至一個第三方的應用,你是走不了這個機制的。 當服務器向瀏覽器傳輸cookie的時候,很容易被劫持。並不是絕對安全的。在大型的項目中,我們的servlet容器。服務器往往不是一台,如果一個用戶的信息落在第一台服務,那么后面請求在訪問的是第二台服務器。那么后面的就訪問不到這個用戶信息了。然后又要重新登陸。Spring 有一個Spring Session外部的存儲來當你的Token Store來存session信息。以前沒有Spring Session 要做這個事情還是挺麻煩的,要在好多個tomcat之間同步session信息,然后保持他們的一致性,

所以出現了另外一種自己實現來基於token 的登陸


基於cookie和sesison常見的風險。也就是一些攻擊方式,以及怎么去防護這些攻擊

結束


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM