springboot+shiro 01 - 实现权限控制
- 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