之前写过Shiro的文章,但是当回过头来整理的时候,发现缺了好多东西,今天重新整理一下。

我们都知道Shiro和secitity都是安全的框架,但是相对于Shiro来说,比较入门简单,所需要的功能基本上都能满足,理解起来也会比较容易。

Shiro是一个有许多特性的全面的安全框架,下面一幅图进行介绍。

可以看出Shiro除了基本的认证、授权、会话管理、加密之外还有许多特性。

Shiro架构:

从架构来说,主要包含三个概念,Subject、SecurityManager、Realms(重要),在使用的时候我们都是围绕这三个概念来进行编码和使用

Shiro的应用不依赖任何的容器,可以在javaSE下使用也可以在javaEE上使用,下面是一张用户登录的例图:

首先理解下面的几个类:

SecurityManager:

Shiro的核心是ScurityManager,它是负责安全认证与授权的,Shiro本身已经实现了所有的细节,我们在使用的时候可以完全把它当做黑盒使用。

SecurityUtils:

本质上是一个工厂,类似Spring中的ApplicationContext,

Subject:

Subject是有点难理解的,有些地方理解为user,其实不然,Subject中文翻译是项目,在下面代码中会表现的很清楚

Realm:

在Shiro中,进行的授权和认证就是由它来操作的,我已开始对授权和认证不是很理解,也不是很明白在代码操作的时候命名在认证的时候,可以获取到授权的信息,为什么还要在进行授权的操作,下面对授权和认证做一下解释:所谓的认证,他相当于人的身份证,就是可以证明你身份的证件,在应用中,就是拿着当前登录的用户的名称与数据库中查询,看是当前登录的用户是否在数据库存在,如果存在,好,说明你是你自己。而所谓的授权,就相当于当你购买火车票的时候,如果你买的硬座,你就只能去硬座的车厢,而不能去软卧等其他车厢,这就相当于限制了你的能力,而在应用中也相当于如此,在授权的时候,会从数据库将你的权限信息获取到,交给Shiro,如果此时你要去访问指定的页面的时候,会首先对你的权限进行校验,看你是否有该权限,如果有就可以访问,没有则不可以访问。

代码讲解:

准备ehcache的xml配置  ,为什么要设置ehcache,是因为如果不设置,会每次刷新页面的时候都会去访问授权的方法,加上缓存之后,可以有效的制止

<?xml version="1.0" encoding="UTF-8"?>
<!--add by shanggq 2018/8/31 end-->
<ehcache name="es"><diskStore path="java.io.tmpdir"/><!--name:缓存名称。maxElementsInMemory:缓存最大数目maxElementsOnDisk:硬盘最大缓存个数。eternal:对象是否永久有效,一但设置了,timeout将不起作用。overflowToDisk:是否保存到磁盘,当系统当机时timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。clearOnFlush:内存数量最大时是否清除。memoryStoreEvictionPolicy:Ehcache的三种清空策略;FIFO,first in first out,这个是大家最熟的,先进先出。LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。--><defaultCachemaxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="false"diskPersistent="false"diskExpiryThreadIntervalSeconds="120"/><!-- 登录记录缓存锁定10分钟 --><cache name="passwordRetryCache"maxEntriesLocalHeap="2000"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="0"overflowToDisk="false"statistics="true"></cache></ehcache>
<!-- add by zhangcf 2018/8/31 start -->

pom.xml

<?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.example</groupId><artifactId>springbootshiro</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>springbootshiro</name><description>Demo project for Spring Boot</description><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.4.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><!--<exclusions>--><!--<exclusion>--><!--<groupId>org.springframework.boot</groupId>--><!--<artifactId>spring-boot-starter-tomcat</artifactId>--><!--</exclusion>--><!--</exclusions>--></dependency><!--!&#45;&#45;用于编译jsp&ndash;&gt;--><!--&lt;!&ndash; https://mvnrepository.com/artifact/org.apache.tomcat.embed/tomcat-embed-jasper &ndash;&gt;--><!--<dependency>--><!--<groupId>org.apache.tomcat.embed</groupId>--><!--<artifactId>tomcat-embed-jasper</artifactId>--><!--</dependency>--><!--&lt;!&ndash;jsp页面使用jstl标签&ndash;&gt;--><!--&lt;!&ndash; https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl &ndash;&gt;--><!--<dependency>--><!--<groupId>javax.servlet.jsp.jstl</groupId>--><!--<artifactId>jstl</artifactId>--><!--</dependency>--><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-configuration-processor --><!-- configuration-processor --><!--用来读取配置文件--><!--<dependency>--><!--<groupId>org.springframework.boot</groupId>--><!--<artifactId>spring-boot-configuration-processor</artifactId>--><!--<optional>true</optional>--><!--</dependency>--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--jpa 对象持久化,利用该jar包,通过bean直接生成数据库表--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><!-- shiro的依赖 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.3.2</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.3.2</version></dependency><!--&lt;!&ndash; https://mvnrepository.com/artifact/net.sf.ehcache/ehcache &ndash;&gt;--><!--<dependency>--><!--<groupId>net.sf.ehcache</groupId>--><!--<artifactId>ehcache</artifactId>--><!--<version>2.10.5</version>--><!--</dependency>--><!--   DRUID是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池(据说是目前最好的连接池,不知道速度有没有BoneCP快)。--><!-- https://mvnrepository.com/artifact/com.alibaba/druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--热部署--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional></dependency><!--spring boot 整合 mybatis 依赖--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.0</version></dependency><!-- json支持 --><dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.4</version><classifier>jdk15</classifier></dependency><!-- 包含支持UI模版(Velocity,FreeMarker,JasperReports), 邮件服务, 脚本服务(JRuby), 缓存Cache(EHCache),任务计划Scheduling(uartz)。 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><!-- 单点登录 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-cas</artifactId><version>1.2.4</version></dependency></dependencies><build><!--表示最终的项目名,--><finalName>springbootshiro</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--用于告诉maven在打包的时候不需要web.xml,否则会报到不到web.xml de错--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-war-plugin</artifactId><version>2.4</version><configuration><failOnMissingWebXml>false</failOnMissingWebXml></configuration></plugin></plugins></build></project>

下面对代码的讲解,我是按照用户一开始登录,到最后的顺序来讲解,如果按照从数据操作到前端访问开始讲的话,有些地方会比较难理解

Controller层的数据   --  前端页面在访问的时候访问的路径

package com.example.springbootshiro.Controller;import com.example.springbootshiro.service.ILoginService;
import com.example.springbootshiro.entity.Role;
import com.example.springbootshiro.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.Map;/**  * @author shanggq* @date 2018/8/31*/
// add by shanggq 2018/8/31  start
@RestController
public class LoginResource {//    //    注入业务层
//    @Autowired
//    private ILoginService iLoginService;
//@GetMapping("/login")public String login() {return "login";}////  POST登录@PostMapping("/login")public String login(@RequestBody Map map) {
//        添加用户认证信息Subject subject = SecurityUtils.getSubject();UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(map.get("username").toString(),map.get("password").toString());subject.login(usernamePasswordToken);return "login";}
//@RequestMapping("/index")public String index(){return  "index";}
//
//@PostMapping("/error")public String error(){return  "error";}
//
//    @RequestMapping("/addUser")
//    public String addUser(@RequestBody Map<String,Object> map){
//        User user = iLoginService.addUser(map);
//        return  "addUser id ok \n"+user;
//    }
//角色初始化
//
//    @RequestMapping("addRole")
//    public String addRole(@RequestBody Map<String ,Object> map ){
//        Role role = iLoginService.addRole(map);
//        return "addRole is ok ! \n" +role;
//    }
//注解的使用,表示访问该方法需要怎样的权限和角色
//
//
//    @RequiresRoles("admin")
//    @RequiresPermissions("create")
//    @RequestMapping("/create")
//    public  String create(){
//        return  "Create success!";
//    }
}
// add by shanggq 2018/8/31 endn

上面代码显示,如果当前端按照post的格式进行数据访问login的时候,会请求到login的方法中,接收的参数是一个map,也就是说在页面中进行数据请求的时候,会将登录的用户名和密码或者其他数据进行传递,然后使用@RequetsBody将数据封装到map集合中,然后下面将数据放到了 UsernamePasswordToken(用户名密码认证机制)对象中,然后此时将该对象放到了用 SecurityUtils对象获取到的Subject对象中,SecutityUtils在上面提到过,他相当于Application,本质上是一个工厂类,然后使用该工厂获取到了Subject,在上面的构架图中我们可以看到,Application Code最终是给了Subject,然后Subject却又给了SecutityManager对象,也就是说现在可以理解为页面传递的用户的信息会存储在SecutityManager中。

Realm的编写(最重要的。进行用户的授权和认证)

package com.example.springbootshiro.shiro;import com.example.springbootshiro.mapper.UserInfoMapper;
import com.example.springbootshiro.service.ILoginService;
import com.example.springbootshiro.entity.Permission;
import com.example.springbootshiro.entity.Role;
import com.example.springbootshiro.entity.User;
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 org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/*** @author shanggq* @date 2018/8/31*/
// add by shanggq 2018/8/31  start
@Component
public class MyShiroRealm extends AuthorizingRealm {/*** 用於数据库的数据的访问,** @Resource 按照名称进行数据的注入* @Autowired 按照类型进行数据的注入*/@Autowiredprivate UserInfoMapper tokentokentoken;/*** 权限信息(授权)** @param principals* @return 如果用户正常退出,缓存会自动消除* 如果用户非正常退出,缓存也会自动消除* 如果修改了用户的权限,而用户没有退出系统,修改的权限无法立即生效--需手动实现,放在service中* <p>* 如果不做缓存,shiro会有自己的时间的间隔机制,时间为2分钟*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {/** 当没有使用缓存的时候,不断的刷新页面的话,这个代码会不断的执行,其实没有* 必要每次都要重新设置权限的信息,所以需要在放到缓存中进行管理,当放到环迅中这样的haunted* doGetAuthorizationInfo就会只执行一次,缓存在过期之后再次* */SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();User user = (User) principals.getPrimaryPrincipal();List<Role> list = new ArrayList<>();list = tokentokentoken.findRoleListByName(user.getUid());user.setRoles(list);//        设置角色,权限,
//        info.addRole("admin");
//        info.addStringPermission("query");//            从数据库中设置角色和权限,分别设置到 SimpleAuthorizationInfo 中返回for (Role role : user.getRoles()) {info.addRole(role.getRolename());for (Permission permission : role.getPermissions()) {info.addStringPermission(permission.getPermission());}}return info;}/*** 身份认证** @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//        获取用户的输入的账号String userName = (String) token.getPrincipal();User user = tokentokentoken.findByUserName(userName);if (user == null) {return null;}
//        加密方式,获取密码在存入的时候,加密的盐
//       明文。若存在,将此用户存放到登录认证info中,不需要我们自己进行密码的比较,shiro会自动给我们进行比较return new SimpleAuthenticationInfo(userName, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName());}
}
// add by shanggq 2018/8/31 end

Realm中分为身份认证和授权两个方法,一开始我对这两个方法不理解,因为我的思路是你身份认证完成之后说明你可以进行登录,这样不就完成控制了么,为什么还需要权限认证,当我在继续往下面看的时候,发现并不是这样的。数据全部的操作全部交给SecurityManager对象去操作。

下面配置核心对象 SecurityManager。在这里我们使用的是spring boot 搭建的工程,所以这里也使用java配置,来完成对象注入到spring容器中。

package com.example.springbootshiro.shiro;import org.apache.shiro.cache.ehcache.EhCacheManager;
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.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;
import java.util.LinkedHashMap;/*** 进行相应的bena的初始化** @author shanggq* @date 2018/8/31*/
// add by shanggq 2018/8/31  start
@Configuration
public class ShiroConfiguration {//将自己的验证方式加入容器,因为自己的的容器配置了授权和认证的方法@Beanpublic MyShiroRealm myShiroRealm() {MyShiroRealm myShiroRealm = new MyShiroRealm();return myShiroRealm;}/*shiro缓存管理器* 需要注入其他的实体类中* 1,安全管理器。secuityManager  最核心的管理器,但是配置完成之后基本上不会进行操作* */@Beanpublic EhCacheManager ehCacheManager() {System.out.println("ShiroConfiguration.getEhCacheManager()");EhCacheManager cacheManager = new EhCacheManager();
//        指定配置shiro的文件cacheManager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");return cacheManager;}//   权限管理,配置主要是Realm的管理认证@Bean(name = "securityManager")public SecurityManager securityManager() {DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
//        设置realmmanager.setRealm(myShiroRealm());
//        注入缓存manager.setCacheManager(ehCacheManager());return manager;}//    Filter  工厂,设置对应的过滤条件和跳转条件@Beanpublic ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//        必须要设置的  SecurityManagershiroFilterFactoryBean.setSecurityManager(securityManager);
//        设置的拦截器
//        HashMap<String, String> hashMap = new HashMap<>();LinkedHashMap<String, String> hashMap = new LinkedHashMap<>();//  配置退出的过滤器,其中的具体的退出代码shiro已经替我们实现了hashMap.put("/logout", "logout");
//        登录页面需要的权限hashMap.put("/login", "anon");//对所有的用户进行认证 当所有的认证都通过的时候才可以访问路径,hashMap.put("/**", "authc");//登录页shiroFilterFactoryBean.setLoginUrl("/login");//登录成功之后跳转到首页shiroFilterFactoryBean.setSuccessUrl("/index");//错误页面。认证不通过的时候跳转shiroFilterFactoryBean.setUnauthorizedUrl("/error");shiroFilterFactoryBean.setFilterChainDefinitionMap(hashMap);return shiroFilterFactoryBean;}//    加入注解的使用,不加入这个注解不生效@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager);return advisor;}
}
// add by shanggq 2018/8/31 end

首先创建你继承了 AuthorizingRealm的 对象类,将该对象创建出来使用@Bean放到spring的容器中,然后再创建 EhCacheManager 对象,为什么要创建该对象的呢,我们在权限控制的代码中已经加了说明,是因为现权限在开发中一般很少去发生改变,如果我们每次在刷新页面的时候都要去数据库中获取数据,判断当前用户有没有当前的权限,会加大数据库的访问,所以我们可以将数据放在缓存中,这样在每次刷新页面的时候,不会都去访问该授权的代码,而首先是去缓存中查询数据,当缓存过期之后,才会去访问授权部分的代码。然后在创建核心的对象SecutityManager对象,将继承身份认证的对象和缓存的对象都放到SecutityManager对象中,然后返回。然后创建下面的 ShiroFilterFactoryBean 对象,该对象在使用传统的配置文件的时候,也需要配置该类,目的是为了进行数据的拦截。将拦截的数据传递给上面创建的对象,然后完成身份和权限的校验,不知道在这里读者有没有在脑海中出现一条思路,也就是说,用户在将数据提交的时候,Subject会接收到数据,然后将数据会传递给SecutityManager对象,这里又有疑问了,数据是怎么传递给SecutityManager对象的呢,所以我就去查看源码,结果找到了下面的代码

也就是说,subject会将前端接收到的数据给SecutityManager,然而Realm返回的数据和 EhCacheManager缓存对象添加到SecutityManager对象中,但是该对象需要被谁给触发呢,所以就到了最后面的拦截器,ShiroFilterFactoryBean,那我们是不是可以理解为,当有请求过来的时候,会触发拦截器,而拦截器回去调用SecutityManager对象,而SecutityManager对象再去分别调用Realm和EhcacheManager对象,分别获取数据,此时用户的身份,权限都已经获取到,就到了下面的权限的设置,我们将全部的权限信息放到了 LinkedHashMap 集合中,而且还可以使用 ShiroFilterFactoryBean 对象设置登录、失败、首页所需要跳转的页面,然后将集合放到  ShiroFilterFactoryBean 对象中。下面对权限的信息进行说明(常用的五种)

Anon:表示可以不用登录直接访问

Authc:表示需要登录之后才可以访问

Perms:表示权限

Roles:表示角色

User:表示用户

AuthorizationAttributeSourceAdvisor对象表示的是开启对方法上的注解的扫描,因为有些方法是在当具有一定的权限的时候才可以访问的,如果不初始化该类的实例,方法上的注解是不起作用的,原因如下

是因为,代理的 方式,应该都知道,java的代理方式,一种是传统的代理方式,当有接口的时候才会使用,一种是cglib代理的方式,传统的代理方式是针对接口而言的,由于此时接口上是没有shiro的注解的,所以此时的注解是不起作用的,所以需要对上面的对象进行实例化,当然也可以改用cglib代理的方式,选择代理的方式是如果有接口就是用传统的代理方式,如果没有接口则使用cglib代理的方式。

相关的注解   - -   在方法上使用,可以完成对方法权限的管理

Shiro权限控制(二)相关推荐

  1. Apache Shiro权限控制框架简介

    Apache Shiro权限控制框架简介 要想实现权限控制,可以自己写代码实现,蓄力都的权限控制可以通过过滤器Filter实现,细粒度的权限控制是基于代理对象结合自定义的注解和反射技术来实现,反射技术 ...

  2. Shiro权限控制+整合shiro

    Shiro权限控制 0.1传统的权限认证方式 特点:为每个人单独的分配权限模块,能够实现权限控制,但是当公司人员庞大之后,非常难管理 上述权限控制如何设计表? 关系:员工和菜单权限的关系:多对多 员工 ...

  3. tp3.2.3权限控制二之后台管理部分,及菜单栏目显示问题

    上篇记录了一下权限控制部分的实现过程,以及实现的代码.但那些只是实现了简单的权限控制,具体的后台当然要有用户的管理,用户组的管理,规则管理等.这篇主要是写后台部分,和上篇凑成一个完整的环. 第一篇文章 ...

  4. shiro权限控制登陆成功页面跳转问题

    在开发中使用了shiro进行权限控制,遇到一个页面跳转问题:当用户账号密码都正确的时候并没有跳转到登陆成功页面. 在shiroFilter过滤器中配置了登陆成功路径没有反应.注意:我使用的是表单验证. ...

  5. JFinal配合Shiro权限控制在FreeMarker模板引擎中控制到按钮粒度的使用

    实现在FreeMarker模板中控制对应按钮的显示隐藏主要用到了Shiro中的hasRole, hasAnyRoles, hasPermission以及Authenticated等方法,我们可以实现T ...

  6. Shiro权限控制笔记要点

    一.Shiro 1.1 权限管理过滤器解释: Authentication :身份认证/登录,验证用户是不是拥有相应的身份: Authorization :授权,即权限验证,验证某个已认证的用户是否拥 ...

  7. 【Spring-boot】shiro权限控制

    缓存使用redis,自定义ShiroRedisCache.ShiroRedisCacheManager用于存储用户缓存信息 自定义MyShiroToken继承自AuthenticationToken. ...

  8. k26.第十一章 K8s进阶篇-细粒度权限控制 (二)

    2. RBAC实践 创建一个名为deployment-clusterrole的clusterrole ​ a) 该clusterrole只允许创建Deployment.Daemonset.Statef ...

  9. shiro 方法级别细粒度权限控制_Shiro的认证和权限控制

    从类别上分,有两大类: - 认证:你是谁?–识别用户身份. - 授权:你能做什么?–限制用户使用的功能. 权限的控制级别 从控制级别(模型)上分: - URL级别-粗粒度 - 方法级别-细粒度 - 页 ...

最新文章

  1. BNUOJ 52305 Around the World 树形dp
  2. superset docker方式安装
  3. python3基础3--数据类型--数据运算--表达式if -else-while-for
  4. POJ 1523 SPF (割点 点双连通分量)
  5. 整理的3500个常用汉字的调用字典
  6. 天津理工大学c语言上机题库,天津理工大学C语言上机报告题目加答案.doc
  7. python输入成绩求总分和平均分_python脚本如何输入成绩求平均分?
  8. cdn.cache.php,CDN缓存不命中诊断 - 在线工具
  9. 全网首发:JDK绘制文字系列博文汇总
  10. 使用Python PyQt5实现一个简单的图像识别软件
  11. 运筹学笔记 整数规划
  12. 几个免费下载原版图书的网站
  13. 公众平台 php,微信公众平台PHP开发
  14. 苹果和android无线充电,这款mophine无线充电器,苹果安卓放上去就能充
  15. 360 千亿级数据量的 Kafka 深度实践
  16. 查找mac系统下的隐藏文件以及隐藏文件夹的方法
  17. java递归多层(多节点)xml和map互相转换
  18. 【机器学习基础】线性基函数模型
  19. 矩阵论 - 9 - 线性无关、基、维数
  20. 搜狗输入法4.2android,搜狗手机输入法增加适配系统 推Android专用版

热门文章

  1. 认识Android(常用布局,控件,四大组件,动画,自定义控件及异常消息处理机制)
  2. 微生物16S测序数据的正确打开方式
  3. 剑指offer学习--实现单例模式
  4. Android开发笔记(序)
  5. 关于UTF8,UTF16,UTF32,UTF16-LE,UTF16-BE
  6. 展讯6500平台架构
  7. 数据源——中青数据百融
  8. Excel排序,数据透视图,公式预测
  9. linux下的pmap命令
  10. 微信小程序05---聊天室的搭建