Springboot+SpringMVC+Myabtis整合shiro許可權控制
最近也被這個難題搞的我頭都大了額。寫下此篇文章獻給自己和廣大朋友。如果有不懂的地方可以加企鵝號詢問哦。
企鵝號:2054861587,不一定會時時在,但如果有空的話就會給你回答
maven依賴:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.5</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.5</version> </dependency>
專案下面新建Shiro配置類。
以下為配置類程式碼:
這裡有個坑,也是這個坑讓我頭疼了好久,就是當你沒有寫自定義的ShiroRealm類時,下面程式碼會瘋狂報錯。
ps:親,記得哦。ShiroRealm類的程式碼在後面。
@Configuration public class ShiroConfiguration { @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean(name = "shiroRealm") @DependsOn("lifecycleBeanPostProcessor") public ShiroRealm shiroRealm() { ShiroRealm realm = new ShiroRealm(); return realm; } @Bean(name = "ehCacheManager") @DependsOn("lifecycleBeanPostProcessor") public EhCacheManager ehCacheManager() { EhCacheManager ehCacheManager = new EhCacheManager(); return ehCacheManager; } @Bean("securityManager") public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroRealm()); securityManager.setCacheManager(ehCacheManager());//使用者授權/認證資訊Cache, 採用EhCache 快取 return securityManager; } @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager()); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); Map<String, String> filterChainDefinitionManager = new LinkedHashMap<>(); filterChainDefinitionManager.put("/logout", "logout"); filterChainDefinitionManager.put("/user/**", "authc,roles[user]"); filterChainDefinitionManager.put("/shop/**", "authc,roles[shop]"); filterChainDefinitionManager.put("/admin/**", "authc,roles[admin]"); filterChainDefinitionManager.put("/login", "anon");//anon 可以理解為不攔截 filterChainDefinitionManager.put("/ajaxLogin", "anon");//anon 可以理解為不攔截 filterChainDefinitionManager.put("/static/**", "anon");//靜態資源不攔截 //filterChainDefinitionManager.put("/**", "authc,roles[user]");//其他資源全部攔截 filterChainDefinitionManager.put("/**", "anon"); // filterChainDefinitionManager.put("/controller/MangerController", "anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setSuccessUrl("/"); shiroFilterFactoryBean.setUnauthorizedUrl("/403"); return shiroFilterFactoryBean; } @Bean @ConditionalOnBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); daap.setProxyTargetClass(true); return daap; } /** * 開啟shiro aop註解支援 * 使用代理方式,所以需要開啟程式碼支援 * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(securityManager); return aasa; }
ShiroRealm類:
這裡的User、role、Permission為實體類,實體類程式碼最下面貼出,mangerService為實現層,下面也會放出程式碼。
public class ShiroRealm extends AuthorizingRealm { private Logger logger=LoggerFactory.getLogger(ShiroRealm.class); @Autowired private MangerService mangerService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { logger.info("##################執行Shiro許可權認證##################"); User user= (User) principalCollection.getPrimaryPrincipal(); if(user!=null){ SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); //使用者的角色集合 info.addRoles(user.getRolelist()); //使用者的許可權集合 info.addStringPermissions(user.getPerminslist()); return info; } return null; } /** * 登入認證 * @param authenticationToken * @return */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken; logger.info("驗證當前SubJect時獲取到的token為:"+token.toString()); User user=mangerService.getUser(token.getUsername()); System.out.println(token.getUsername()); if(user!=null){ //若存在,將此使用者存放到登入認證info中,無需自己做密碼對比,Shiro會為我們進行密碼對比校驗 List<Role> rlist = mangerService.findRoleByUid(user.getUS_ID());//獲取使用者角色 List<Permission> plist = mangerService.findPermissionByUid((user.getUS_ID()));//獲取使用者許可權 List<String> roleStrlist=new ArrayList<String>();////使用者的角色集合 List<String> perminsStrlist=new ArrayList<String>();//使用者的許可權集合 for (Role role : rlist) { roleStrlist.add(role.getName()); } for (Permission permission : plist) { perminsStrlist.add(permission.getName()); } user.setRolelist(roleStrlist); user.setPerminslist(perminsStrlist); Session session = SecurityUtils.getSubject().getSession(); session.setAttribute("user", user);//成功則放入session //若存在,將此使用者存放到登入認證info中,無需自己做密碼對比,Shiro會為我們進行密碼對比校驗 return new SimpleAuthenticationInfo(user, user.getUS_PASS(), getName()); } return null; } }
mangerService程式碼如下,其餘方法就不貼出了,只貼出上面ShiroRealm類呼叫的三個類:
public List<Role> findRoleByUid(String us_id) { return mdao.findRoleByUid(us_id); } public List<Permission> findPermissionByUid(String us_id) { return mdao.findPermissionByUid(us_id); } public User getUser(String username) { return mdao.getUser(username); }
mdao程式碼如下:
public User getUser(String username);
List<Role> findRoleByUid(String us_id); List<Permission> findPermissionByUid(String us_id);
都是最普通的程式碼,o(∩_∩)o 哈哈 下面上XML程式碼:
<select id="getUser" resultType="user" parameterType="String"> select us_id,us_name,us_name_kp,us_pass from bas_user where us_name=#{param1} </select> <select id="findRoleByUid" resultType="Role" parameterType="String"> select * from u_role where id=#{param1} </select> <select id="findPermissionByUid" resultType="Permission" parameterType="String"> select * from u_permission where id=#{param1} </select>
Controller層:
@RequestMapping(value = "/login") public String login(HttpServletRequest request, HttpServletResponse response,Model model) { response.setContentType("text/html;charset=utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password); Subject subject=SecurityUtils.getSubject(); try { logger.info("對使用者["+username+"]開始進行登入驗證...驗證開始"); subject.login(usernamePasswordToken); logger.info("對使用者[" + username + "]進行登入驗證..驗證通過"); } catch (UnknownAccountException e) { logger.info("對使用者[" + username + "]進行登入驗證..驗證未通過,未知賬戶"); logger.info("未知帳號"); }catch (IncorrectCredentialsException ice){ logger.info("對使用者[" + username + "]進行登入驗證..驗證未通過,錯誤的憑證"); logger.info("密碼不正確"); }catch(LockedAccountException lae){ logger.info("對使用者[" + username + "]進行登入驗證..驗證未通過,錯誤的憑證"); logger.info("帳戶已鎖定"); }catch (AuthenticationException e){ logger.info("使用者名稱或密碼不正確"); } User user= (User) subject.getPrincipal(); return "index"; }
博主承認上面的程式碼有點繞,如果實在不懂,歡迎提問,或者你直接照抄也木有問題。
表結構的兄弟不要著急,相信你們看了實體類程式碼後也會建表了,如果還是不明白,那就請繼續往下面看,博主再說詳細些。
public class User { private String US_ID; //使用者ID private String US_NAME; //使用者名稱 private String US_PASS; //密碼 private List<String> rolelist; private List<String> perminslist; 以下省略N多的GET/SET/Tostring方法. }
Role實體類:
private String id; private String name;//角色名稱 private String type;//角色型別
pemins實體類:
private String id; private String url;//url地址 private String name;//url描述
OK後臺程式碼搞定了。
資料庫表還不知道怎麼建的同學,看著博主的 實體類。String或int 為資料庫的資料型別,
user表當中沒有rolelist、perminslist。只有使用者ID、使用者名稱、密碼
user表當中沒有rolelist、perminslist。只有使用者ID、使用者名稱、密碼
user表當中沒有rolelist、perminslist。只有使用者ID、使用者名稱、密碼
重要的事情說三遍。
還不懂?那就舉個例子咯:
pemins實體類舉例。
private String id;
private String url;//url地址
private String name;//url描述
那麼我們在資料庫當中應該這麼定義:
create table pemis(
id varchar(20),
url varchar(50),
name varchar(80)
)
那麼pemins這個表我們就新建好了,有幾個實體類就有幾張表,親。如果還不會,額去找你的資料庫老師吧。
JSP頁面呼叫:
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
放在最上面,不要問為啥,我就是要勵志站在頂端的男人。
<shiro:authenticated>使用者已經登入顯示此內容<br/></shiro:authenticated><br/>
<shiro:hasRole name="manager">manager角色登入顯示此內容<br/></shiro:hasRole>
<shiro:hasRole name="admin">admin角色登入顯示此內容<br/></shiro:hasRole>
<shiro:hasRole name="normal">normal角色登入顯示此內容<br/>
</shiro:hasRole><br/> <shiro:hasAnyRoles name="manager,admin">manager or admin 角色使用者登入顯示此內容<br/>
</shiro:hasAnyRoles><br/> <shiro:principal/>-顯示當前登入使用者名稱<br/><br/>
<shiro:hasPermission name="add">add許可權使用者顯示此內容<br/>
</shiro:hasPermission> <shiro:hasPermission name="user:query">user:query許可權使用者顯示此內容<br/>
</shiro:hasPermission>
<shiro:lacksPermission name="user:query">不具有user:query許可權的使用者顯示此內容 <br/></shiro:lacksPermission>
OK,恭喜你成功了