第三節,SpringBoot整合shrio,Redis快取session與許可權
阿新 • • 發佈:2018-11-16
1.建立Springboot專案
省略。。。
pom檔案
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.dencycheng</groupId> <artifactId>demoshiro</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demoshiro</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 引入freemarker包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <!-- shiro許可權控制框架 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> <!-- shiro-redis 開源框架,用於快取session,與許可權 --> <dependency> <groupId>org.crazycake</groupId> <artifactId>shiro-redis</artifactId> <version>2.8.24</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2.配置自定義Realm
這裡面沒有資料庫的連結,用的Map模擬
package com.dencycheng.shiro; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; 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 java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * @anthor DencyCheng * @date 2018/11/4 0004 */ public class CustormRealm extends AuthorizingRealm { Map<String, String> userMap = new HashMap<String, String>(10); { //模擬使用者 userMap.put("dency", "123456"); userMap.put("admin", "123456"); } /** * 根據使用者名稱獲取許可權列表 * * @param userName * @return */ private Set<String> getPermissionsByUserName(String userName) { Set<String> permissions = new HashSet<>(); permissions.add("user:add"); permissions.add("user:remove"); return permissions; } /** * 根據使用者名稱獲取角色列表 * * @param userName * @return */ private Set<String> getRolesByUserName(String userName) { Set<String> roles = new HashSet<>(); roles.add("admin"); roles.add("user"); return roles; } /** * 模擬登陸操作 * * @param userName * @return */ private String getPasswordByUserName(String userName) { return userMap.get(userName); } /** * 授權(檢視是否有許可權) * * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //1.獲取使用者名稱 String userName = (String) principalCollection.getPrimaryPrincipal(); Set<String> roles = getRolesByUserName(userName); Set<String> permissions = getPermissionsByUserName(userName); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); simpleAuthorizationInfo.setRoles(roles); simpleAuthorizationInfo.setStringPermissions(permissions); return simpleAuthorizationInfo; } /** * 認證(登入) * * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //1.獲取使用者名稱 String userName = (String) authenticationToken.getPrincipal(); //2.查詢使用者是否存在 String password = getPasswordByUserName(userName); if (password == null) { return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, password, userName); return authenticationInfo; } }
3.ShiroConfig
package com.dencycheng.shiro; import org.apache.shiro.mgt.*; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.mgt.SessionManager; 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.web.session.mgt.DefaultWebSessionManager; import org.crazycake.shiro.RedisCacheManager; import org.crazycake.shiro.RedisManager; import org.crazycake.shiro.RedisSessionDAO; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.HashMap; import java.util.Map; /** * @anthor DencyCheng * @date 2018/11/5 0005 */ @Configuration public class ShiroConfig { @Bean public CustormRealm getCustormRealm() { return new CustormRealm(); } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(getCustormRealm()); securityManager.setSessionManager(sessionManager()); // 自定義快取實現 使用redis securityManager.setCacheManager(cacheManager()); return securityManager; } @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> map = new HashMap<String, String>(); //登出 map.put("/login", "anon"); map.put("/doLogin", "anon");//對所有使用者認證 map.put("/**", "authc"); //登入 shiroFilterFactoryBean.setLoginUrl("/login"); //首頁 shiroFilterFactoryBean.setSuccessUrl("/index"); shiroFilterFactoryBean.setUnauthorizedUrl("/401"); //錯誤頁面,認證不通過跳轉 shiroFilterFactoryBean.setUnauthorizedUrl("/error"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } /** * 配置shiro redisManager 使用的是shiro-redis開源外掛 * * @return */ @Bean public RedisManager redisManager() { return new RedisManager(); } @Bean public DefaultWebSessionManager sessionManager() { DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); RedisSessionDAO redisSessionDao = new RedisSessionDAO(); redisSessionDao.setRedisManager(redisManager()); sessionManager.setSessionDAO(redisSessionDao); return sessionManager; } /** * cacheManager 快取 redis實現 使用的是shiro-redis開源外掛 * * @return */ public RedisCacheManager cacheManager() { RedisCacheManager redisCacheManager = new RedisCacheManager(); redisCacheManager.setRedisManager(redisManager()); return redisCacheManager; } /** * 開啟Shiro的註解(如@RequiresRoles,@RequiresPermissions),需藉助SpringAOP掃描使用Shiro註解的類,並在必要時進行安全邏輯驗證 * 配置以下兩個bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可實現此功能 */ @Bean public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; } }
4.測試控制器
package com.dencycheng.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @anthor DencyCheng
* @date 2018/11/5 0005
*/
@Controller
public class UserController {
@RequiresPermissions("user:add")
@RequestMapping("/add")
@ResponseBody
public String add(){
return "有許可權";
}
@RequestMapping("/401")
public String noAuth(){
return "401";
}
@RequestMapping("/login")
public String login(){
return "/login";
}
@RequestMapping("/doLogin")
@ResponseBody
public String doLogin(String username,String password){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
subject.login(usernamePasswordToken);
return "成功";
}
}