您好,登錄后才能下訂單哦!
這篇“Shiro在springboot中如何快速實現”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Shiro在springboot中如何快速實現”文章吧。
1、Apache Shiro是一個Java的安全(權限)框架
2、可以容易的開發出足夠好的應用,既可以在JavaEE中使用,也可以在JavaSE中使用
3、shiro可以完成,認證、授權、加密、會話管理,web集成、緩存等
Subject:用戶
SecurityManager:管理所有用戶
Readim:連接數據
1、認證授權模塊:在認證授權模塊中主要包含兩個方面,分別是認證和授權。認證就是指對用戶登錄的情況進行判定;授權就是指對當前用戶所擁有的角色、權限進行獲取并將其交給AuthoriztionInfo,使其能夠將相關信息交給Shiro
2、請求過濾模塊:根據當前用戶所擁有的權限、角色等信息來進行判斷是否具有請求的權限(即是否能夠請求當前要訪問的地址),如果該用戶具有訪問當前請求地址的權限,則放行,否則進行攔截
3、以上是使用shiro框架進行權限認證攔截的最基本實現,此外還可以通過對密碼進行加密,登錄次數限流(redis)等功能重寫來按照自己實際業務情況進行學習
<!-- 后臺攔截--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
@Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier(SecurityManager) DefaultWebSecurityManager securityManager){ ShiroFilterFactiryBean bean = new ShiroFilterFactoryBean() //關聯SecurityManager設置安全管理器 bean.setSecurityManager(securityManager) //添加內置過濾器 /* anon:無需過濾就可以訪問 authc:必須認證了才可訪問(登錄后才可訪問) user:必須擁有"記住我"功能才可訪問 perms:擁有對某個資源的權限才可以訪問 role:擁有某個角色權限才可訪問 */ Map<String,String> filterMap = new LinkedHashMap<>(); //攔截 //filterMap.put("頁面地址","內置過濾器") //filterMap.put("/user/name","anon") //filterMap.put("/user/book","authc") //具有user:add權限時才可以訪問/user/name //perms中的“user:add”與數據庫中對應權限要一致 filterMap.put("/user/name","perms[user:add]") //授權,正常情況下,沒有授權會跳轉到未授權頁面 bean.setUnauthorizedUrl("未授權時跳轉的頁面") //創建一個過濾器鏈(其中內容通過Map存儲) bean.setFilterChainDefinitionMap(FilterMap); //設置登錄請求(登錄的地址添加,當使用"authc"時,如果未登錄,則跳轉到登錄頁面) bean.setLoginUrl("/login") return bean; }
//@Qualifier:引入bena對象 @Bean(name="SecurityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("MyRealm") MyRealm myRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurotyManager(); //關聯MyRealm securityManager.setRealm(myRealm); return securityManager; }
//將自定義的realm對象交給spring //@Bean(name="MyRealm")中name屬性不加默認名稱為方法名 @Bean(name="MyRealm") public MyRealm MyRealm(){ return new MyRealm(); }
class MyRealm extends AuthorizingRealm
授權:
project AthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){ //1、權限信息對象info,用來存放查出的用戶的所有的角色(role)及權限(permission) SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //2、拿到當前登錄的對象信息,通過認證方法SimpleAuthenticationInfo(第一個參數)已經進行存入 User user =(user)SecurityUtils.getSubject().getPrincipal(); //3、將該對象的角色信息進行存入 // 賦予角色 List<Role> roleList = roleService.listRolesByUserId(userId); for (Role role : roleList) { info.addRole(role.getName()); } //4、設置該用戶的權限 infO.addStringPermission(user.getPerms()) //5、將該對象的權限信息進行存入(permissionSet一個權限信息的集合) info.setStringPermissions(permissionSet); return info; }
認證:
project AuthenticationInfo doGetAuthorizationInfo(AuthenticationToken token){ //1、拿到用戶登陸的信息 UsernamePasswordToken userToken =(UsernamePasswordToken) token; //2、通過用戶名(userToken.getUsername)獲取數據庫中的對象user //如果獲取對象user為空則該用戶不從在,返回return null(拋出用戶不存在異常) if (user == null) { throw new UnknownAccountException("賬號不存在!"); //或直接 return null; } //3、密碼認證,有shiro完成(AuthenticationInfo是一個接口,SimpleAuthenticationInfo是其接口的實現類) //也可對密碼進行加密 如MD5 MD5鹽值 return new SimpleAuthenticationInfo("用戶對象信息(user)","通過用戶從數據庫中獲得的用戶密碼(user.password)","") }
//獲取當前用戶 Subject subject = SecurityUtils.getSubject(); //封裝用戶的登錄數據(username:用戶登陸時傳入的賬號;password:用戶登陸時傳入的密碼) UsernamePasswordToken token = new UsernamePasswordToken(username,password); //執行登錄(如果有異常則登錄失敗,沒有異常則登錄成功,在Shiro中已經為我們封裝了登錄相關的異常,直接使用即可) try{ subject.login(token);//執行登錄成功后 return "首頁" }catch(UnknowAccountException e){//用戶名不存在 return "login" }catch(IncorrectCredentialsException e){//密碼不存在 return "login" } 注意:該方法中登錄失敗后返回的是跳轉的頁面,故不可用@ResponseBody
package com.lingmeng.shiro; import com.lingmeng.pojo.entity.Admin; import com.lingmeng.pojo.entity.Permission; import com.lingmeng.pojo.entity.Role; import com.lingmeng.pojo.resp.BaseResp; import com.lingmeng.service.AdminService; import com.lingmeng.service.RoleService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashSet; import java.util.Set; public class MyRealm extends AuthorizingRealm { @Autowired RoleService roleService; @Autowired AdminService adminService; //授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //獲取用戶信息 Subject subject = SecurityUtils.getSubject(); Admin admin =(Admin) subject.getPrincipal(); //獲取用戶的權限及角色信息 BaseResp baseResp = roleService.selectOne(admin.getUsername()); Role role = (Role) baseResp.getData(); //將獲取的角色及權限進行存入 if (role!=null){ //角色存入 info.addRole(role.getName()); //權限信息進行存入 Set<String> perms = new HashSet<>(); for (Permission perm : role.getPerms()) { perms.add(perm.getUrl()); } info.setStringPermissions(perms); } return info; } //認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //獲取登錄信息(登錄的賬號) String username =(String)authenticationToken.getPrincipal(); // UsernamePasswordToken userToken =(UsernamePasswordToken) authenticationToken;拿到登錄時傳入的賬號和密碼對象 //從數據庫中查詢該對象的信息 Admin admin = adminService.selectOne(username); if (admin==null){ throw new UnknownAccountException("賬號不存在"); } return new SimpleAuthenticationInfo(admin,admin.getPassword(),this.getName()); } }
package com.lingmeng.controller; import com.lingmeng.pojo.entity.Admin; import com.lingmeng.pojo.resp.BaseResp; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.web.bind.annotation.*; @RestController public class AdminController { @PostMapping("background/login") public BaseResp login(@RequestBody Admin admin){ Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(admin.getUsername(), admin.getPassword()); try{ subject.login(token); return BaseResp.SUCCESS("登錄成功",null,null); }catch (UnknownAccountException e){//賬號不存在 return BaseResp.FAIL(201,"賬號不存在"); }catch(IncorrectCredentialsException incorrectCredentialsException){//密碼錯誤 return BaseResp.FAIL(201,"密碼錯誤") ; } } @GetMapping("/background/exitLogin") public BaseResp exitLogin(){ Subject subject = SecurityUtils.getSubject(); System.out.println(subject.getPrincipal()); try{ subject.logout();//退出登錄 return BaseResp.SUCCESS("退出登錄",null,null); }catch(Exception e){ return BaseResp.FAIL(202,"退出失敗"); } } }
package com.lingmeng.config; import com.lingmeng.shiro.MyRealm; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; @Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(securityManager); //配置請求攔截并存入map中 /* anon:無需過濾就可以訪問 authc:必須認證了才可訪問(登錄后才可訪問) user:必須擁有"記住我"功能才可訪問 perms:擁有對某個資源的權限才可以訪問 role:擁有某個角色權限才可訪問 */ Map<String, String> map = new LinkedHashMap<>(); map.put("/background/**","authc"); map.put("background/login","anon"); bean.setFilterChainDefinitionMap(map); //設置未授權跳轉地址 bean.setUnauthorizedUrl(""); //設置登錄地址 bean.setLoginUrl("/background/login"); return bean; } @Bean("securityManager") public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm){ return new DefaultWebSecurityManager(myRealm); } @Bean() public MyRealm myRealm(){ return new MyRealm(); } }
以上是一些shiro在springboot中的基本用法,希望能夠對大家學習有所幫助(代碼中的實體,角色,權限根據自己數據庫查詢結果進行替換即可)。
以上就是關于“Shiro在springboot中如何快速實現”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。