springboot +shiro 詳細(ehcache快取)
阿新 • • 發佈:2018-11-19
1 匯入maven座標
-
<!--shiro start--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> <!--shiro end--> <!-- https://mvnrepository.com/artifact/net.sf.ehcache/ehcache-core --> <!--本地快取+shiro--> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.11</version> </dependency>
2 resouce 下的ehcache.xml檔案
-
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <!-- 配置快取資料夾 預設:path="java.io.tmpdir" eternal="true":ture為設定快取永不過期 通過註解當進行增刪改時清除快取,這樣就會是同步資料庫的快取了 --> <diskStore path="D:\\temp"/> <defaultCache maxElementsInMemory="10000" eternal="true" maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </defaultCache> <cache name="LL" maxElementsInMemory="10000" eternal="true" maxElementsOnDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> <persistence strategy="localTempSwap"/> </cache> </ehcache>
3 shiro 配置類shiroconfig
-
package com.czxy.web.config; import com.czxy.web.shiro.BosCredentialsMatcher; import com.czxy.web.shiro.BosRealm; import org.apache.shiro.authc.credential.CredentialsMatcher; import org.apache.shiro.cache.ehcache.EhCacheManager; import org.apache.shiro.realm.Realm; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.mgt.SecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; /** * 在ShiroConfig中做什麼事情呢? * 1 配置shiro安全管理器,向安全管理器中注入Realm域 * 2 配置Realm域:注入密碼比較器 * 3 配置密碼比較器 * 4 配置攔截路徑和放行路徑 */ @Configuration public class ShiroConfig { /** * 配置安全管理器,並且注入Realm域 * * @param realm * @return */ @Bean public SecurityManager securityManager(Realm realm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(realm); securityManager.setCacheManager(ehCacheManager());//這個如果呼叫多次是同一個物件 return securityManager; } /** * Credentials:憑證/證書 --- * <p> * 配置Realm域,注入密碼比較器 * * @param credentialsMatcher * @return */ @Bean public BosRealm realm(CredentialsMatcher credentialsMatcher) { BosRealm bosRealm = new BosRealm(); bosRealm.setCredentialsMatcher(credentialsMatcher); return bosRealm; } /** * 密碼比較器 * * @return */ @Bean public CredentialsMatcher credentialsMatcher() { // return new HashedCredentialsMatcher("MD5"); return new BosCredentialsMatcher(); } /** * 配置攔截路徑和放行路徑 * * @param securityManager * @return */ @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { System.out.println("ShiroConfiguration.shirFilter()"); // shiro過濾器工廠類 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必須設定 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); //攔截器----Map集合 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); //配置退出 過濾器,其中的具體的退出程式碼Shiro已經替我們實現了 filterChainDefinitionMap.put("/login*", "anon"); filterChainDefinitionMap.put("/user/login*", "anon"); filterChainDefinitionMap.put("/validatecode.jsp*", "anon"); filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/images/**", "anon"); filterChainDefinitionMap.put("/data/**", "anon"); // 許可權控制 粗粒度對頁面進行控制 // (放入角色也可以控制權限) filterChainDefinitionMap.put("/pages/base/area**", "roles[base]"); // (放入許可權也可以控制權限) filterChainDefinitionMap.put("/pages/base/courier**", "perms[courier:add]"); // /** 匹配所有的路徑 // 通過Map集合組成了一個攔截器鏈 ,自頂向下過濾,一旦匹配,則不再執行下面的過濾 // 如果下面的定義與上面衝突,那按照了誰先定義誰說了算 // /** 一定要配置在最後 filterChainDefinitionMap.put("/**", "authc"); // 將攔截器鏈設定到shiro中 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); // 如果不設定預設會自動尋找Web工程根目錄下的"/login.jsp"頁面 shiroFilterFactoryBean.setLoginUrl("/login.html"); // 登入成功後要跳轉的連結 shiroFilterFactoryBean.setSuccessUrl("/index.html"); //未授權介面; shiroFilterFactoryBean.setUnauthorizedUrl("/unauthority.html"); return shiroFilterFactoryBean; } /** * 開啟shiro aop註解支援 * 使用代理方式;所以需要開啟程式碼支援 * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } /** * 開啟cglib代理 * * @return */ @Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); creator.setProxyTargetClass(true); return creator; } /** * ehcache 快取 * * @return */ @Bean public EhCacheManager ehCacheManager() { System.out.println("ShiroConfiguration.getEhCacheManager()"); EhCacheManager cacheManager = new EhCacheManager(); cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml"); return cacheManager; } }
4 自定義ream域
-
package com.czxy.web.shiro; import com.czxy.domain.system.Permission; import com.czxy.domain.system.Role; import com.czxy.domain.system.User; import com.czxy.service.system.PermisionService; import com.czxy.service.system.RoleService; import com.czxy.service.system.UserService; 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.springframework.beans.factory.annotation.Autowired; import java.util.List; public class BosRealm extends AuthorizingRealm { @Autowired private UserService userService; @Autowired private RoleService roleService; @Autowired private PermisionService permission; //授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("授權"); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); //通過shiro 中獲的使用者名稱 User primaryPrincipal = (User) principals.getPrimaryPrincipal(); //通過使用者名稱進行角色的查詢 List<Role> byUserId = roleService.findByUserId(primaryPrincipal); for (Role role : byUserId) { authorizationInfo.addRole(role.getKeyword()); } //通過使用者名稱進行查詢許可權 List<Permission> permission = this.permission.findPermission(primaryPrincipal); for (Permission permission1 : permission) { authorizationInfo.addStringPermission(permission1.getKeyword()); } return authorizationInfo; } //認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("認證"); UsernamePasswordToken upToken= (UsernamePasswordToken)token; User user = userService.QueryUserByUpToken(upToken.getUsername()); if(user!=null){ //Object principal, Object credentials, String realmName return new SimpleAuthenticationInfo(user,user.getPassword(),this.getName()); } //表示不存在 return null; } }
5.密碼比較器
-
package com.czxy.web.shiro; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; import org.apache.shiro.crypto.hash.Sha256Hash; public class BosCredentialsMatcher extends SimpleCredentialsMatcher { @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { System.out.println("密碼比較器"); UsernamePasswordToken upUptoken = (UsernamePasswordToken) token; //獲取頁面輸入的密碼 String pwd = new String(upUptoken.getPassword()); //對頁面密碼進行加密 upUptoken.getUsername撒鹽 String Rpwd = new Sha256Hash(pwd, upUptoken.getUsername(), 3).toString(); System.out.println(Rpwd); //獲取資料庫中的密碼 String dbpwd = info.getCredentials().toString(); return equals(Rpwd, dbpwd); } }
6認證controller
-
package com.czxy.web.system; import com.czxy.domain.system.User; import com.czxy.service.system.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpSession; @RestController @RequestMapping("/user") public class UserController { @GetMapping("/login") public ResponseEntity<String> LoginIn(User user, HttpSession httpSession) { try { // 通過shiro進行使用者登入 SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), user.getPassword())); //登入成功把使用者名稱儲存到session中 User loginUser = (User) SecurityUtils.getSubject().getPrincipal(); httpSession.setAttribute("loginUser", loginUser); return new ResponseEntity<>("登入成功", HttpStatus.OK); } catch (Exception e) { return new ResponseEntity<>("登入失敗",HttpStatus.INTERNAL_SERVER_ERROR); } } @GetMapping("/logout") public ResponseEntity<String> Loginout( HttpSession httpSession) { httpSession.removeAttribute("loginUser"); SecurityUtils.getSubject().logout(); return new ResponseEntity<>(HttpStatus.OK); } }
7 授權controller
-
package com.czxy.web.system; import com.czxy.domain.system.Menu; import com.czxy.domain.system.User; import com.czxy.domain.vo.DataGridResult; import com.czxy.service.system.MenuService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController @RequestMapping("/menu") public class ShowMenuController { @Autowired private MenuService menuService; @GetMapping @RequestMapping("/showMenu") public ResponseEntity<List<Menu>> showMent(){ User user = (User) SecurityUtils.getSubject().getPrincipal(); List<Menu> list= menuService.findMenuByUser(user); return new ResponseEntity<>(list,HttpStatus.OK); } }