基於Spring Boot整合shiro的基本使用
阿新 • • 發佈:2020-08-07
1.引入依賴
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.3</version> </dependency>
2.瞭解shiro的三大物件(轉載至:https://blog.csdn.net/qq_41430393/article/details/87730198
1.Subject(主體)
應用程式碼的直接互動物件就是Subject,也就是說Shiro對外的核心API就是Subject,Subject代表了當前“使用者”,這個使用者不是指具體的某一個人,可以說與當前應用互動的任何東西都是Subject,與Subject的所有互動都會委託給SecurityManager來執行,可以理解為Subject只是一個充當門面的,真正的幕後老大是SecurityManager,SecurityManager才是實際的執行者。
2.SecurityManager(安全管理器)
所有與安全有關的操作都會與SecurityManager進行互動,並且SecurityManager管理者所有的Subject,可以看出它才是Shiro的核心,它負責與Shiro的其他元件進行互動,它相當於SpringMvc中的dispatcherServlet(前端控制器)的角色。
3.Realm
Shiro從Realm獲取安全資料(使用者、角色、許可權),就是說SecurityManager要驗證使用者身份,那麼它需要從Realm獲取相應的使用者進行比較以確定使用者身份是否合法,也需要從Realm獲取使用者的角色\許可權來判斷使用者是否能進行一系列操作。可以把Realm看作DataSource資料來源.
3.配置shiroConfig類以及shiroReaml類
shiroConfig類(將三大物件聯絡起來,配置需要攔截的頁面):
@Configuration //交由spring管理 public class shiroConfig { //自底向上建立,並繫結//ShiroFilterFactoryBean,第三步 @Bean public ShiroFilterFactoryBean getFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); //關聯安全管理器 bean.setSecurityManager(securityManager); //新增shiro的內建過濾器 /* anon:無需認證就可以訪問 authc:必須認證才能訪問 驗證密碼和使用者 user:必須擁有 記住我 功能才能用 perms:擁有對某個資源的許可權才能訪問 role:擁有某個角色許可權才能訪問 */ //使用map新增相應頁面的過濾 Map<String, String> filterMap=new LinkedHashMap<>(); //因為是鏈式過濾,所以得先過濾範圍小的 //不僅需要登陸還得擁有許可權才可訪問 //表示資料庫中user表中的欄位perm為user:update才表示有這個許可權訪問改路徑 filterMap.put("/user/update","perms[user:update]"); filterMap.put("/user/add","perms[user:add]"); //需要登陸即可訪問的頁面 filterMap.put("/user/*","authc"); //設定未登入時,進入需要許可權的頁面時,跳轉的登陸頁面 bean.setLoginUrl("/toLogin"); //設定許可權不足時跳轉的頁面 bean.setUnauthorizedUrl("/noAuth"); bean.setFilterChainDefinitionMap(filterMap); return bean; } //DefaultWebSecurityManager,第二步 @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("getRealm") shiroRealm shiroRealm){ DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager(); //關聯realm securityManager.setRealm(shiroRealm); return securityManager; } //建立realm物件,第一步@Bean交由spring管理 @Bean public shiroRealm getRealm(){ return new shiroRealm(); } }
shiroReaml類(用於實現使用者認證和授權的操作)
//授權和認證都會經過此類 public class shiroRealm extends AuthorizingRealm { @Autowired userService service; //授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { Subject subject = SecurityUtils.getSubject();//獲取當前使用者 user currentUser = (user) subject.getPrincipal();//從當前使用者中取出Principal(認證時已儲存了user) SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//是AuthorizationInfo的實現類 info.addStringPermission(currentUser.getPerm());//根據資料庫中的perm欄位新增相應的許可權 return info; } //認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken; user user = service.findByUsername(token.getUsername()); //使用者名稱校驗,檢視是否存在使用者名稱 if(user==null){ return null;//返回null表示賬號不存在,會丟擲異常UnknownAccountException } //密碼校驗,shiro自帶檢驗 //若是密碼錯誤會丟擲異常IncorrectCredentialsException return new SimpleAuthenticationInfo(user,user.getPassword(),""); //第一個引數是principal作用是傳遞資訊的,如認證完後可以將資料庫中查詢的user放進去, //供授權時,給相應的使用者新增相應資料庫中的許可權 } }
4.配置Controller的實現
@Controller public class myController { @RequestMapping({"/","/index"}) public String index(){ return "index"; } @RequestMapping("/user/add") public String add(){ return "user/add"; } @RequestMapping("/user/update") public String update(){ return "user/update"; } @RequestMapping("/toLogin") public String toLogin(){ return "login"; } @RequestMapping("/login") public String login(String username, String password, Model model){ Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username,password); try { subject.login(token);// 該操作會將token轉至手寫的realm類中的doGetAuthenticationInfo方法中認證登陸 return "index"; }catch (UnknownAccountException e){//使用者名稱不存在 model.addAttribute("msg","使用者名稱不存在"); return "login"; }catch (IncorrectCredentialsException e){//密碼不存在 model.addAttribute("msg","密碼錯誤"); return "login"; } } @RequestMapping("/noAuth") @ResponseBody public String noAuth(){ return "許可權不足!"; } @RequestMapping("/logout") @ResponseBody public String logout(){ SecurityUtils.getSubject().logout();//登出 return "登出成功!"; } }