填坑*
還記得exclude = DataSourceAutoConfiguration.class
嗎?
在第三週_上裏, 我們報了一個數據源配置的錯誤(如下圖)
這個錯誤的原因主要有兩個可能性:
- 你的application.properties文件中沒有數據庫相關的配置
- 你的application.properties沒有被項目識別到
首先我自己是已經將application.properties中將有關數據庫的配置寫好了, 但依然提示這個錯誤,
包括在配置文件中的變量, 程序裏也取不到;
遂懷疑是這個配置文件沒有被加載進來…
於是想出了這麼一個權宜之計(exclude = DataSourceAutoConfiguration.class)
寫代碼嘛, 就是折騰, 在重啓項目->重啓IDEA->重啓電腦之後, 依然沒有解決這個問題.
於是我把項目push到了碼雲上並把原項目刪掉, 從碼雲上clone了一份源碼下來, 居然解決了!
尷尬的是, 有同學照着我的博客, 也把這句加了上去, 結果在項目啓動的時候, 報錯了, 提示找不到mapper, 一開始我以爲是她mapper寫錯了, 一波排查沒搞定…
還是老師厲害, 找到了這個問題, 把這句給刪掉後, 項目成功啓動.
那些被我誤導的同學, 很是抱歉!
完善Shiro配置
上週我們對Shiro安全框架做了簡單的配置, 接下來我們要用上這個框架了!
還記得我們之前編寫過的一個測試插入用戶數據的方法嗎? (見第四周)
在方法名上加上@Rollback(value = false)
, 作用是讓數據庫在執行完測試後, 不執行回滾, 也就是會把我們測試用的插入數據保留下來
接下來我們執行一次測試, 如果測試通過的話, 可以看到用戶表中成功多了一條數據
現在我們的密碼在數據庫中就是經過加密後的密文, 沒有相應的認證來匹配是不行的
我們可以在ShiroConfig中編寫一個CredentialsMatcher
方法來匹配, 並在我們的Realm中用上它
修改登錄接口
還記得我們的登錄接口嗎?
@GetMapping("/login")
public ResultJson login(){
ResultJson resultJson = new ResultJson("200","登陸成功","");
return resultJson;
}
這裏只是簡單的做了個get方法, 並直接返回了數據, 接下來我們要完善這個接口
思路是這樣的:
- 將其改爲Post
- 實例化一個
UsernamePasswordToken
- 通過
SecurityUtils.getSubject()
一個subject - 利用
subject.login()
對我們的token
進行認證 - 如果登錄成功後, 會生成一個
session
- 根據認證的不同結果, 返回對應的數據
@PostMapping("/login")
public ResultJson login(String userName, String password){
ResultJson resultJson;
/*
if("admin".equals(userName)&&"admin".equals(password)){
resultJson = new ResultJson("200","登陸成功","");
}else {
String data = "userName:"+userName+"password:"+password;
resultJson = new ResultJson("0","登陸失敗,用戶名或密碼不正確",data);
}
* */
try {
UsernamePasswordToken token = new UsernamePasswordToken(userName,password);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
String sessionID = subject.getSession().getId().toString();
HashMap<String,String> map = new HashMap<>();
map.put("token",sessionID);
resultJson = new ResultJson("200","登錄成功",map);
}catch (UnknownAccountException e){//未知賬號
resultJson = new ResultJson("400","用戶名或密碼錯誤","");
}catch (IncorrectCredentialsException e){//密碼錯誤
resultJson = new ResultJson("400","用戶名或密碼錯誤","");
}catch (DisabledAccountException e){//用戶被禁用
resultJson = new ResultJson("400","此用戶被禁用","");
}catch (Exception e){//未知錯誤
resultJson = new ResultJson("400","未知錯誤,請聯繫管理員!","");
}
return resultJson;
}
接下來可以啓動項目, 用swagger來做一個測試
認證接口
在前端頁面中, 我們可以通過頁面的跳轉, 和控制數據的顯示來對用戶的操作進行限制;
那麼如果後端的接口地址暴露了, 用戶就可以繞過前端頁面, 直接通過接口來對我們的數據庫進行操作;
這顯然是非常不安全的!!!
那麼我們在後端中就要實現對接口的訪問限制
首先我們先在UserController中定義三個接口
接口: 尚未登陸
@GetMapping("/without_login")
public ResultJson withoutLogin(){
return new ResultJson("400","您還未登錄!",null);
}
接口: 沒有權限
@GetMapping("/unauthorized")
public ResultJson unauthorized(){
return new ResultJson("401","沒有權限!",null);
}
接口: 添加用戶
在這裏我們傳遞了一個token
參數, 並且在使用@RequiresRoles
註解, 來判斷用戶角色爲admin或者manager的用戶可以操作此接口.
@ApiImplicitParams({
@ApiImplicitParam(name = "token", value = "鑑權用戶",required = true,paramType = "header")
})
@GetMapping("/addUser")
@RequiresRoles(value = {"admin","manager"},logical = Logical.OR)
public ResultJson addUser(){
return new ResultJson("200","成功",null);
}
前面我們只添加了一條用戶的數據, 並沒有設置其角色
方便測試, 我又多加了兩條用戶數據
接着我們在角色表中插入三條角色數據
最後在用戶角色表中設置各個用戶的角色
配置訪問限制
打開我們的ShrioConfig
添加如下配置, 對應我們的接口操作的安全限制
最後來測試下把 !
登錄接口中:
輸入錯誤的用戶名和密碼:
正確的時候:
對添加用戶接口進行操作
沒有傳遞token或傳遞錯誤的token時候
角色不爲admin或manager時
成功時: