環境 SpringBoot2.0java
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
ShiroConfig
import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 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 shirFilter(SecurityManager securityManager) { System.out.println("ShiroConfiguration.shirFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //攔截器. Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); // 配置不會被攔截的url 順序判斷 //配置退出 過濾器,其中的具體的退出代碼Shiro已經替咱們實現了 filterChainDefinitionMap.put("/dologin", "anon"); filterChainDefinitionMap.put("/logout", "anon"); //<!-- 過濾鏈定義,從上向下順序執行,通常將/**放在最爲下邊 -->:這是一個坑呢,一不當心代碼就很差使了; //<!-- authc:全部url都必須認證經過才能夠訪問; anon:全部url都均可以匿名訪問--> filterChainDefinitionMap.put("/**", "authc"); // 若是不設置默認會自動尋找Web工程根目錄下的"/login.jsp"頁面 shiroFilterFactoryBean.setLoginUrl("/login"); // 登陸成功後要跳轉的連接 shiroFilterFactoryBean.setSuccessUrl("/index"); //未受權界面; shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * 憑證匹配器 * (因爲咱們的密碼校驗交給Shiro的SimpleAuthenticationInfo進行處理了 * ) * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:這裏使用MD5算法; hashedCredentialsMatcher.setHashIterations(1);//散列的次數,好比散列兩次,至關於 md5(md5("")); return hashedCredentialsMatcher; } @Bean public MyShiroRealm myShiroRealm(){ MyShiroRealm myShiroRealm = new MyShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); return securityManager; } /** * 開啓shiro aop註解支持. * 使用代理方式;因此須要開啓代碼支持; * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } }
自定義一個MyShiroRealmweb
import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class MyShiroRealm extends AuthorizingRealm { /*認證 主要是用來進行身份認證的,也就是說驗證用戶輸入的帳號和密碼是否正確。*/ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //把AuthenticationToken轉換成UsernamePasswordToken UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken)authenticationToken; //獲取username String username=usernamePasswordToken.getUsername(); //根據username從數據庫查詢信息(注入並調用UserService方法),此處省略 //根據獲取的用戶信息,決定是否拋出AuthenticationException異常,此處寫死 if(username.equals("unknown")){ throw new UnknownAccountException("用戶不存在!"); } if (username.equals("lock")) { throw new LockedAccountException("用戶被鎖定!"); } //構建並返回AuthenticationInfo,一般是SimpleAuthenticationInfo //principal:能夠是username,也能夠是用戶實體對象 //credentials:從數據庫獲取的密碼 //realmName:當前realm對象的name Object principal=username; //Object credentials="123456"; Object credentials=new SimpleHash("MD5", "123456", "", 1); String realmName=this.getName(); SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(principal, credentials, realmName); return info; } /** * 受權 權限信息,包括角色以及權限 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("權限配置-->MyShiroRealm.doGetAuthorizationInfo()"); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); //若是身份認證的時候沒有傳入User對象,這裏只能取到userName //也就是SimpleAuthenticationInfo構造的時候第一個參數傳遞須要User對象 String userName = (String)principalCollection.getPrimaryPrincipal(); //根據username從數據庫查詢角色和權限信息,此處省略 //構造角色數據 if(userName.equals("zhangsan")){ authorizationInfo.addRole("role1"); authorizationInfo.addRole("role2"); } if(userName.equals("lisi")){ authorizationInfo.addRole("role1"); } //構造權限數據 if(userName.equals("zhangsan")){ authorizationInfo.addStringPermission("user:list"); authorizationInfo.addStringPermission("user:add"); authorizationInfo.addStringPermission("user:delete"); } if(userName.equals("lisi")){ authorizationInfo.addStringPermission("user:list"); } return authorizationInfo; } public static void main(String[] args) { String algorithmName="MD5"; String source="123456"; String salt=""; int hashIterations=1; Object result=new SimpleHash(algorithmName, source, salt, hashIterations); System.out.println(result); } }
ShiroTestController 模擬登錄後訪問url測試
import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.UnauthorizedException; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.subject.Subject; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("") public class ShiroTestController { @RequestMapping(value = "/dologin") public String login() { System.out.println("------登陸-------"); String msg = ""; //String username = "zhangsan"; String username = "lisi"; String password = "123456"; UsernamePasswordToken token = new UsernamePasswordToken(username, password); Subject subject = SecurityUtils.getSubject(); try { subject.login(token); if (subject.isAuthenticated()) { return "登陸成功"; } else { return "登陸失敗"; } } catch (IncorrectCredentialsException e) { msg = "登陸密碼錯誤. Password for account " + token.getPrincipal() + " was incorrect."; System.out.println(msg); } catch (ExcessiveAttemptsException e) { msg = "登陸失敗次數過多"; System.out.println(msg); } catch (LockedAccountException e) { msg = "賬號已被鎖定. The account for username " + token.getPrincipal() + " was locked."; System.out.println(msg); } catch (DisabledAccountException e) { msg = "賬號已被禁用. The account for username " + token.getPrincipal() + " was disabled."; System.out.println(msg); } catch (ExpiredCredentialsException e) { msg = "賬號已過時. the account for username " + token.getPrincipal() + " was expired."; System.out.println(msg); } catch (UnknownAccountException e) { msg = "賬號不存在. There is no user with username of " + token.getPrincipal(); System.out.println(msg); } catch (UnauthorizedException e) { msg = "您沒有獲得相應的受權!" + e.getMessage(); System.out.println(msg); } return "登陸"; } @RequestMapping(value = "logout", method = RequestMethod.GET) public String logout() { System.out.println("------退出-------"); Subject subject = SecurityUtils.getSubject(); if (subject != null) { try{ subject.logout(); }catch(Exception ex){ } } return "退出成功"; } @RequestMapping("/index") public String index(){ System.out.println("------進入首頁-------"); return "進入首頁"; } @RequestMapping("/unauthorized") public String unauthorized(){ System.out.println("------未受權-------"); return "未受權"; } @RequestMapping("/userList") @RequiresPermissions("user:list") public String userList(){ System.out.println("------用戶列表-------"); return "用戶列表"; } @RequestMapping("/userAdd") @RequiresPermissions("user:add") public String userAdd(){ System.out.println("------用戶添加-------"); return "用戶添加"; } @RequestMapping("/userDelete") @RequiresPermissions("user:delete") public String userDelete(){ System.out.println("------用戶刪除-------"); return "用戶刪除"; } }