- sb_shiro_session

<?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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.20.BUILD-SNAPSHOT</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.huarui</groupId> <artifactId>sb_shiro_session</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sb_shiro_session</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version> <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.3.2</version> </dependency> <!-- https://mvnrepository.com/artifact/org.crazycake/shiro-redis --> <dependency> <groupId>org.crazycake</groupId> <artifactId>shiro-redis</artifactId> <version>3.1.0</version> <exclusions> <exclusion> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> </exclusion> </exclusions> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.47</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.8.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> </pluginRepository> </pluginRepositories> </project>

server.port=8089 #thymeleaf spring.thymeleaf.cache=false #redis spring.redis.host=39.108.85.204 spring.redis.port=6379 #shiro redis shiro.redis.host=39.108.85.204:6379 shiro.redis.timeout=1800000 #mysql spring.datasource.url=jdbc:mysql://39.108.85.204:3306/mybatis?useUnicode=true&characterEncoding=utf8 spring.datasource.username=youxiu326 spring.datasource.password=zz123456.ZZ spring.datasource.driver-class-name=com.mysql.jdbc.Driver #jpa spring.jpa.database = MYSQL spring.jpa.show-sql = true spring.jpa.hibernate.ddl-auto = update spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
- entity

/** * Created by lihui on 2019/1/29. * * 用戶登錄 通過 code+password * */ @Entity @Table(name="sys_operator") public class Operator implements Serializable{ private String id; private String name; private String code; private String password; /** * 擁有角色 */ private List<Role> roles; @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "sys_operator_role", joinColumns = { @JoinColumn(name = "operator_id", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "role_id", referencedColumnName = "id") }) public List<Role> getRoles() { return roles; } public void setRoles(List<Role> roles) { this.roles = roles; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Id @GeneratedValue(generator = "sys_uid") @GenericGenerator(name = "sys_uid", strategy = "uuid") public String getId() { return id; } public void setId(String id) { this.id = id; } }

/** * Created by lihui on 2019/1/29. * 角色 */ @Entity @Table(name="sys_role") public class Role implements Serializable { private String id; /** * 角色 */ private String name; /** * 角色擁有資源 */ private List<Resource> resources; @Id @GeneratedValue(generator = "sys_uid") @GenericGenerator(name = "sys_uid", strategy = "uuid") public String getId() { return id; } public void setId(String id) { this.id = id; } @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "sys_role_resource", joinColumns = { @JoinColumn(name = "role_id", referencedColumnName = "id") }, inverseJoinColumns = {@JoinColumn(name = "resource_id", referencedColumnName = "id") }) public List<Resource> getResources() { return resources; } public void setResources(List<Resource> resources) { this.resources = resources; } public String getName() { return name; } public void setName(String name) { this.name = name; } }

package com.huarui.entity; import com.fasterxml.jackson.annotation.JsonIgnore; import org.hibernate.annotations.GenericGenerator; import javax.persistence.*; import java.io.Serializable; import java.util.List; /** * Created by lihui on 2019/1/29. * 資源 */ @Entity @Table(name="sys_resource") public class Resource implements Serializable{ private String id; /** * 權限名稱 */ private String name; /** * 權限URL */ private String url; /** * 是否需要授權 */ private boolean authorization; /** * 上級權限 */ private Resource parent; /** * 下級權限 */ private List<Resource> children; @Id @GeneratedValue(generator = "sys_uid") @GenericGenerator(name = "sys_uid", strategy = "uuid") public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public boolean isAuthorization() { return authorization; } public void setAuthorization(boolean authorization) { this.authorization = authorization; } @ManyToOne @JoinColumn(name = "parent_id") @JsonIgnore public Resource getParent() { return parent; } public void setParent(Resource parent) { this.parent = parent; } /** * 級聯刪除 * @return */ @OneToMany(cascade={CascadeType.REMOVE},mappedBy = "parent") public List<Resource> getChildren() { return children; } public void setChildren(List<Resource> children) { this.children = children; } }
一個用戶擁有多個角色 一個角色可以訪問多個資源
表數據
sys_operato "id" "code" "name" "password" "402882ec689886fa016898875c2d0000" "admin" "lihui" "c6cc583c2703c6271ff04981e6225f0f" "402882ec6898b30b016898b35a610000" "test" "test" "4de0fe9cf9f47ce5af891d6182d6c4b7" "402882ec6898ddf0016898de59f10000" "open" "open" "cba0efa9a832d0cf2e1a646db406bdfa" sys_role "id" "name" "1" "admin" "2" "test" sys_operator_role "operator_id" "role_id" "402882ec689886fa016898875c2d0000" "1" "402882ec6898b30b016898b35a610000" "2" sys_resource "id" "authorization" "name" "url" "parent_id" "1" "1" "添加用戶" "/to/add" "" "2" "1" "修改用戶" "/to/update" "" "3" "1" "用戶列表" "/to/list" "" sys_role_resource "role_id" "resource_id" "1" "1" "1" "2" "1" "3" "2" "3"
- dao

public interface RoleDao extends JpaRepository<Role, String> { }

public interface ResourceDao extends JpaRepository<Resource, String> { @Query("select distinct r.resources from Operator as o left join o.roles as r where o.id = ?1") public List<Resource> findResourcesByOperator(String operatorId); @Query("from Resource where authorization=true ") public List<Resource> findAllByAutho(); }

public interface OperatorDao extends JpaRepository<Operator, String> { Operator findByCode(String code); }
- service

public interface OperatorService { Operator findByCode(String code); void save(Operator operator); } @Service public class OperatorServiceImpl implements OperatorService { @Autowired private OperatorDao operatorDao; @Override public Operator findByCode(String code) { return operatorDao.findByCode(code); } @Override public void save(Operator operator) { operatorDao.save(operator); } }

public interface ResourceService { List<Resource> getResourcesByOperator(String operatorId); List<Resource> findAllByAutho(); } @Service public class ResourceServiceImpl implements ResourceService { @Autowired private ResourceDao resourceDao; @Override public List<Resource> getResourcesByOperator(String operatorId) { return resourceDao.findResourcesByOperator(operatorId); } @Override public List<Resource> findAllByAutho() { return resourceDao.findAllByAutho(); } }
- controller
package com.huarui.controller; import com.huarui.entity.Operator; import com.huarui.service.OperatorService; import com.huarui.utils.PasswordUtil; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import java.util.HashMap; import java.util.Map; /** * Created by lihui on 2019/1/29. */ @Controller @RequestMapping("/") public class LoginController { @Autowired private OperatorService operatorService; @RequestMapping("/") public String tologin(){ return "login"; } @RequestMapping("/login") //未登錄自動跳至login public String login(){ return "login"; } @RequestMapping("/403") //沒有權限自動跳至403 public String to403(){ return "403"; } /** * 跳轉至指定頁面 * @param path * @return */ @GetMapping("/to/{url}") public String path(@PathVariable("url")String path){ return path; } @PostMapping("/ajax") public @ResponseBody Map ajax(){ Map map = new HashMap<>(); map.put("state","200"); map.put("msg","成功獲取到數據"); map.put("data","youxiu326@163.com"); return map; } /** * 登錄 * @param operator * @return */ @RequestMapping("/loginAction") public @ResponseBody String loginAction(Operator operator){ if (StringUtils.isBlank(operator.getCode())){ return "編號不能為空"; } if (StringUtils.isBlank(operator.getPassword())){ return "密碼不能為空"; } UsernamePasswordToken token = new UsernamePasswordToken(operator.getCode(), operator.getPassword()); Subject subject = SecurityUtils.getSubject(); subject.login(token); return "登錄成功"; } /** * 注冊 * @param operator * @return */ @RequestMapping("/register") public @ResponseBody String register(Operator operator){ //TODO 編號重復驗證 if (StringUtils.isBlank(operator.getName())){ return "昵稱不能為空"; } if (StringUtils.isBlank(operator.getCode())){ return "編號不能為空"; } if (StringUtils.isBlank(operator.getPassword())){ return "密碼不能為空"; } operator.setPassword(PasswordUtil.saltAndMd5(operator.getPassword(),operator.getName(),2)); operatorService.save(operator); return "注冊成功"; } }
- utils

/** * Created by lihui on 2019/1/29. * MD5加密工具類 */ public class PasswordUtil { /** * @param password 需要加密的次數 * @param username 鹽 * @param hashIterations 加密次數 * @return */ public static String saltAndMd5(String password,String username,int hashIterations){ //加密算法 String algorithmName = "MD5"; //鹽值 Object salt = ByteSource.Util.bytes(username); SimpleHash hash = new SimpleHash(algorithmName, password, salt, hashIterations); return hash.toString();//32位 } }
- config

package com.huarui.config; import com.huarui.entity.Operator; import com.huarui.entity.Resource; import com.huarui.service.ResourceService; import org.apache.shiro.authc.credential.CredentialsMatcher; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.SessionKey; import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.SimpleCookie; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.apache.shiro.web.util.WebUtils; 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.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import javax.servlet.ServletRequest; import java.io.Serializable; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * Created by lihui on 2019/1/29. * 實現session共享 * shiro配置類 */ @Configuration public class ShiroConfig { @Value("${shiro.redis.host}") public String host; @Value("${shiro.redis.timeout}") public int timeout; @Autowired private ResourceService resourceService; //shiro共享session 參考博客: https://www.cnblogs.com/LUA123/p/9337963.html /* 過濾器 anon:所有url都都可以匿名訪問 authc: 需要認證才能進行訪問 user:配置記住我或認證通過可以訪問 */ @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); //攔截器. Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>(); // 配置不會被攔截的鏈接 順序判斷 filterChainDefinitionMap.put("/static/**", "anon"); filterChainDefinitionMap.put("/jquery-1.11.3.min.js", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/loginAction", "anon"); filterChainDefinitionMap.put("/register", "anon"); //配置退出 過濾器,其中的具體的退出代碼shiro已經替我們實現了 filterChainDefinitionMap.put("/logout", "logout"); //<!-- 過濾鏈定義,從上向下順序執行,一般將*//**放在最為下邊 --> //<!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問--> //TODO 添加權限攔截 List<Resource> resources = resourceService.findAllByAutho(); for(Resource re : resources){ filterChainDefinitionMap.put(re.getUrl(), String.format("perms[%s]", re.getUrl())); } filterChainDefinitionMap.put("/**", "authc"); // 如果不設置默認會自動尋找Web工程根目錄下的"/login.html"頁面 shiroFilterFactoryBean.setLoginUrl("/login"); // 登錄成功后要跳轉的鏈接 shiroFilterFactoryBean.setSuccessUrl("/index"); //未授權界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403"); //自定義攔截器 //shiroFilterFactoryBean.getFilters().put("authc", new SimpleFormAuthenticationFilter()); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } /** * 自定義 認證 授權 */ @Bean public MyShiroRealm myShiroRealm(){ MyShiroRealm myShiroRealm = new MyShiroRealm(); return myShiroRealm; } /** * 4. 配置LifecycleBeanPostProcessor,可以來自動的調用配置在Spring IOC容器中 Shiro Bean 的生命周期方法 * //TODO 該方法指定為static 否則無法初始化@Value * 參考博客: https://blog.csdn.net/wuxuyang_7788/article/details/70141812 * @return */ @Bean public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * 5. 啟用IOC容器中使用Shiro的注解,但是必須配置第四步才可以使用 * * @return */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { return new DefaultAdvisorAutoProxyCreator(); } /** * 密碼校驗器 */ @Bean public CredentialsMatcher myCredentialsMatcher() { HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher(); credentialsMatcher.setHashAlgorithmName("MD5");//MD5加密 credentialsMatcher.setHashIterations(2);//加密兩次 return credentialsMatcher; } /** * 配置SecurityManager * */ @Bean public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); // 設置realm securityManager.setSessionManager(sessionManager()); // 設置sessionManager // securityManager.setCacheManager(redisCacheManager()); // 配置緩存的話,退出登錄的時候crazycake會報錯,要求放在session里面的實體類必須有個id標識 return securityManager; } /** * redis 管理器 * @return */ @Bean public RedisManager redisManager() { RedisManager redisManager = new RedisManager(); // crazycake 實現 redisManager.setHost(host); redisManager.setTimeout(timeout); return redisManager; } /** * 緩存管理器 * @return */ @Bean public RedisCacheManager redisCacheManager() { RedisCacheManager cacheManager = new RedisCacheManager(); // crazycake 實現 cacheManager.setRedisManager(redisManager()); return cacheManager; } /** * session dao 持久到redis * @return */ @Bean public RedisSessionDAO sessionDAO() { RedisSessionDAO sessionDAO = new RedisSessionDAO(); // crazycake 實現 sessionDAO.setRedisManager(redisManager()); sessionDAO.setSessionIdGenerator(new JavaUuidSessionIdGenerator()); // Session ID 生成器 return sessionDAO; } @Bean public SimpleCookie cookie() { SimpleCookie cookie = new SimpleCookie("SHAREJSESSIONID"); // cookie的name,對應的默認是 JSESSIONID cookie.setHttpOnly(true); cookie.setPath("/"); // path為 / 用於多個系統共享JSESSIONID return cookie; } /** * session 默認管理器 * @return */ @Bean public DefaultWebSessionManager sessionManager() { //解決doReadSession多次訪問 DefaultWebSessionManager sessionManager = new CustomDefaultWebSessionManager(); sessionManager.setGlobalSessionTimeout(timeout); // 設置session超時 sessionManager.setDeleteInvalidSessions(true); // 刪除無效session sessionManager.setSessionIdCookie(cookie()); // 設置JSESSIONID sessionManager.setSessionDAO(sessionDAO()); // 設置sessionDAO return sessionManager; } /** * 配置RedisTemplate,充當數據庫服務 * @return */ @Bean public RedisTemplate<String, Operator> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Operator> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(connectionFactory); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<Operator>(Operator.class)); return redisTemplate; } /** * 解決doReadSession多次訪問問題 * */ public static class CustomDefaultWebSessionManager extends DefaultWebSessionManager{ @Override protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException { Serializable sessionId = getSessionId(sessionKey); if(sessionId == null){ return super.retrieveSession(sessionKey); } ServletRequest request = WebUtils.getRequest(sessionKey); Object sessionObj = request.getAttribute(sessionId.toString()); if (sessionObj != null) { return (Session) sessionObj; } Session s = super.retrieveSession(sessionKey); if (request != null && null != sessionId) { request.setAttribute(sessionId.toString(), s); } return s; } } }

package com.huarui.config; import com.huarui.entity.Operator; import com.huarui.entity.Resource; import com.huarui.service.OperatorService; import com.huarui.service.ResourceService; import com.huarui.utils.PasswordUtil; 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.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; /** * Created by lihui on 2019/1/29. * * 自定義Realm */ public class MyShiroRealm extends AuthorizingRealm{ @Autowired private OperatorService operatorService; @Autowired private ResourceService resourceService; //授權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); //取出當前登錄用戶 Operator operator = (Operator) principalCollection.getPrimaryPrincipal(); //獲得當前登錄用戶所擁有的所有資源 List<Resource> resources = resourceService.getResourcesByOperator(operator.getId()); if(resources!=null && resources.size()>0){ for(Resource p:resources){ authorizationInfo.addStringPermission(p.getUrl());//添加權限 } } return authorizationInfo; } //認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //獲取用戶編號 與密碼 UsernamePasswordToken upToken = (UsernamePasswordToken)authenticationToken; String usercode = (String)upToken.getPrincipal(); String password = String.valueOf(upToken.getPassword()); Operator operator = operatorService.findByCode(usercode); if (operator==null){ throw new AuthenticationException("用戶編號不存在"); }else if(!operator.getPassword().equals(PasswordUtil.saltAndMd5(password,operator.getName(),2))){ throw new AuthenticationException("密碼不正確"); } //返回認證信息由父類 進行認證 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( operator, //用戶名 password, //密碼 ByteSource.Util.bytes(operator.getName()),//鹽 getName() //realm name ); return authenticationInfo; } //清空shiro緩存的權限 public void clearAuthz(){ this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals()); } }
- html
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org" > <head> <base th:href="${#httpServletRequest.getContextPath()+'/'}"> <meta charset="UTF-8"> <title>登錄頁面</title> </head> <body> <h3>這是登錄頁面</h3> <form action="loginAction"> 編號:<input name="code"/> <br/> 密碼:<input name="password"/> <br/> <input type="submit" value="登錄"> </form> <br/> <a href="logout" target="_blank">登出</a> <br/> <br/> <br/> <form action="register"> 姓名:<input name="name"/> <br/> 編號:<input name="code"/> <br/> 密碼:<input name="password"/> <br/> <input type="submit" value="注冊"> </form> <br/> <a href="/to/add" target="_blank">去添加界面(admin角色可以訪問)</a> <br/> <a href="/to/update" target="_blank">去修改界面(admin角色可以訪問)</a> <br/> <a href="/to/list" target="_blank">去列表界面(admin和test 角色可以訪問)</a> <br/> <a href="/to/open" target="_blank">去開放界面(登錄了可以訪問)</a> <br/> </body> </html>
<br/> <a href="/to/add" target="_blank">去添加界面(admin角色可以訪問)</a> <br/> <a href="/to/update" target="_blank">去修改界面(admin角色可以訪問)</a> <br/> <a href="/to/list" target="_blank">去列表界面(admin和test 角色可以訪問)</a> <br/> <a href="/to/open" target="_blank">去開放界面(登錄了可以訪問)</a> <br/> 說明: //<!-- authc:所有url都必須認證通過才可以訪問; anon:所有url都都可以匿名訪問--> //TODO 添加權限攔截 List<Resource> resources = resourceService.findAllByAutho(); for(Resource re : resources){ filterChainDefinitionMap.put(re.getUrl(), String.format("perms[%s]", re.getUrl())); } filterChainDefinitionMap.put("/**", "authc"); 所有的resources資源需要擁有權限才能訪問, 如果資源表中不存在的,則登錄就可以訪問 看表 1 1 添加用戶 /to/add 2 1 修改用戶 /to/update 3 1 用戶列表 /to/list 【/to/open】不存在資源表中,所以登錄就可以訪問 admin用戶 擁有admin角色 可以訪問【列表上的所有資源】 test用戶 擁有test角色 可以訪問【/to/list】
測試1: 不登錄情況下 所有a標簽進入不了,
測試2: 登錄test用戶pwd:111111 可以訪問去列表界面 去開放界面
測試3:登錄admin用戶pwd:111111 可以訪問列出的所有界面
github: https://github.com/youxiu326/sb_shiro_session.git