综合概述

Shiro是Apache旗下的一个开源项目,它是一个非常易用的安全框架,提供了包括认证、授权、加密、会话管理等功能,与Spring Security一样属基于权限的安全框架,但是与Spring Security 相比,Shiro使用了比较简单易懂易于使用的授权方式。Shiro属于轻量级框架,相对于Spring Security简单很多,并没有security那么复杂。

优势特点

它是一个功能强大、灵活的、优秀的、开源的安全框架。

它可以胜任身份验证、授权、企业会话管理和加密等工作。

它易于使用和理解,与Spring Security相比,入门门槛低。

主要功能

  • 验证用户身份
  • 用户访问权限控制
  • 支持单点登录(SSO)功能
  • 可以响应认证、访问控制,或Session事件
  • 支持提供“Remember Me”服务
  • .......

框架体系

Shiro 的整体框架大致如下图所示(图片来自互联网):

Authentication(认证), Authorization(授权), Session Management(会话管理), Cryptography(加密)代表Shiro应用安全的四大基石。

它们分别是:

  • Authentication(认证):用户身份识别,通常被称为用户“登录”。
  • Authorization(授权):访问控制。比如某个用户是否具有某个操作的使用权限。
  • Session Management(会话管理):特定于用户的会话管理,甚至在非web 应用程序。
  • Cryptography(加密):在对数据源使用加密算法加密的同时,保证易于使用。

除此之外,还有其他的功能来支持和加强这些不同应用环境下安全领域的关注点。

特别是对以下的功能支持:

  • Web支持:Shiro 提供的 web 支持 api ,可以很轻松的保护 web 应用程序的安全。
  • 缓存:缓存是 Apache Shiro 保证安全操作快速、高效的重要手段。
  • 并发:Apache Shiro 支持多线程应用程序的并发特性。
  • 测试:支持单元测试和集成测试,确保代码和预想的一样安全。
  • “Run As”:这个功能允许用户在许可的前提下假设另一个用户的身份。
  • “Remember Me”:跨 session 记录用户的身份,只有在强制需要时才需要登录。

主要流程

在概念层,Shiro 架构包含三个主要的理念:Subject, SecurityManager 和 Realm。下面的图展示了这些组件如何相互作用,我们将在下面依次对其进行描述。

Shiro执行流程图(图片来自互联网)

三个主要理念:

  • Subject:代表当前用户,Subject 可以是一个人,也可以是第三方服务、守护进程帐户、时钟守护任务或者其它当前和软件交互的任何事件。
  • SecurityManager:管理所有Subject,SecurityManager 是 Shiro 架构的核心,配合内部安全组件共同组成安全伞。
  • Realms:用于进行权限信息的验证,我们自己实现。Realm 本质上是一个特定的安全 DAO:它封装与数据源连接的细节,得到Shiro 所需的相关的数据。在配置 Shiro 的时候,你必须指定至少一个Realm 来实现认证(authentication)和/或授权(authorization)。

我们需要实现Realms的Authentication 和 Authorization。其中 Authentication 是用来验证用户身份,Authorization 是授权访问控制,用于对用户进行的操作授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。

实现案例

接下来,我们就通过一个具体的案例,来讲解如何进行Shiro的整合,然后借助Shiro实现登录认证和访问控制。

生成项目模板

为方便我们初始化项目,Spring Boot给我们提供一个项目模板生成网站。

1.  打开浏览器,访问:https://start.spring.io/

2.  根据页面提示,选择构建工具,开发语言,项目信息等。

3.  点击 Generate the project,生成项目模板,生成之后会将压缩包下载到本地。

4.  使用IDE导入项目,我这里使用Eclipse,通过导入Maven项目的方式导入。

添加相关依赖

清理掉不需要的测试类及测试依赖,添加 Maven 相关依赖,这里需要添加上WEB、Swagger、JPA和Shiro的依赖,Swagger的添加是为了方便接口测试。

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.</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1..RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.louis.springboot</groupId>
<artifactId>demo</artifactId>
<version>0.0.-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.</version>
</dependency>
<!-- jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<!-- 打包时拷贝MyBatis的映射文件 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/sqlmap/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build> </project>

添加相关配置

1.添加数据源和jpa相关配置

将application.properties文件改名为application.yml ,并在其中添加MySQL数据源连接信息。

注意:

这里需要首先创建一个MySQL数据库,并输入自己的用户名和密码。这里的数据库是springboot。

另外,如果你使用的是MySQL 5.x及以前版本,驱动配置driverClassName是com.mysql.jdbc.Driver。

application.yml

server:
port:
spring:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8
username: root
password:
jpa:
show-sql: true # 默认false,在日志里显示执行的sql语句
database: mysql
hibernate.ddl-auto: update #指定为update,每次启动项目检测表结构有变化的时候会新增字段,表不存在时会新建,如果指定create,则每次启动项目都会清空数据并删除表,再新建
properties.hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
database-platform: org.hibernate.dialect.MySQL5Dialect
hibernate:
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl #指定jpa的自动表生成策略,驼峰自动映射为下划线格式
#physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

2. 添加swagger 配置

添加一个swagger 配置类,在工程下新建 config 包并添加一个 SwaggerConfig 配置类。

SwaggerConfig.java

package com.louis.springboot.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration
@EnableSwagger2
public class SwaggerConfig { @Bean
public Docket createRestApi(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
} private ApiInfo apiInfo(){
return new ApiInfoBuilder()
.title("SpringBoot API Doc")
.description("This is a restful api document of Spring Boot.")
.version("1.0")
.build();
} }

编写业务代码

添加一个用户类User,包含用户名和密码,用来进行登录认证,另外用户可以拥有角色。

User.java

package com.louis.springboot.demo.model;

import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany; @Entity
public class User { @Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = true)
private String name;
private String password;
@OneToMany(cascade = CascadeType.ALL,mappedBy = "user")
private List<Role> roles; public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} 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;
}
}

添加一个角色类Role,表示用户角色,角色拥有可操作的权限集合。

Role.java

package com.louis.springboot.demo.model;

import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; @Entity
public class Role { @Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String roleName;
@ManyToOne(fetch = FetchType.EAGER)
private User user;
@OneToMany(cascade = CascadeType.ALL,mappedBy = "role")
private List<Permission> permissions; public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getRoleName() {
return roleName;
} public void setRoleName(String roleName) {
this.roleName = roleName;
} public User getUser() {
return user;
} public void setUser(User user) {
this.user = user;
} public List<Permission> getPermissions() {
return permissions;
} public void setPermissions(List<Permission> permissions) {
this.permissions = permissions;
}
}

添加一个权限类Permission,表示资源访问权限。

Permission.java

package com.louis.springboot.demo.model;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne; @Entity
public class Permission { @Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String permission;
@ManyToOne(fetch = FetchType.EAGER)
private Role role; public Long getId() {
return id;
} public void setId(Long id) {
this.id = id;
} public String getPermission() {
return permission;
} public void setPermission(String permission) {
this.permission = permission;
} public Role getRole() {
return role;
} public void setRole(Role role) {
this.role = role;
}
}

添加一个DAO基础接口,用来被其他DAO继承。

BaseDao.java

package com.louis.springboot.demo.dao;

import java.io.Serializable;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository; @NoRepositoryBean
public interface BaseDao<T, I extends Serializable>
extends PagingAndSortingRepository<T, I>, JpaSpecificationExecutor<T> { }

添加一个UserDao,用来操作用户信息。

UserDao.java

package com.louis.springboot.demo.dao;

import com.louis.springboot.demo.model.User;

public interface UserDao extends BaseDao<User, Long> {

    User findByName(String name);

}

添加一个RoleDao,用来操作角色信息。

RoleDao.java

package com.louis.springboot.demo.dao;

import com.louis.springboot.demo.model.Role;

public interface RoleDao extends BaseDao<Role, Long> {

}

添加一个LoginService服务接口。

LoginService.java

package com.louis.springboot.demo.service;

import com.louis.springboot.demo.model.Role;
import com.louis.springboot.demo.model.User; public interface LoginService { User addUser(User user); Role addRole(Role role); User findByName(String name); }

添加一个LoginServiceImpl,实现服务功能,这里为了方便,在插入角色的时候会默认设置其权限。

LoginServiceImpl.java

package com.louis.springboot.demo.service.impl;

import java.util.ArrayList;
import java.util.List;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.louis.springboot.demo.dao.RoleDao;
import com.louis.springboot.demo.dao.UserDao;
import com.louis.springboot.demo.model.Permission;
import com.louis.springboot.demo.model.Role;
import com.louis.springboot.demo.model.User;
import com.louis.springboot.demo.service.LoginService; @Service
@Transactional
public class LoginServiceImpl implements LoginService { @Autowired
private UserDao userDao;
@Autowired
private RoleDao roleDao; //添加用户
@Override
public User addUser(User user) {
userDao.save(user);
return user;
} //添加角色
@Override
public Role addRole(Role role) {
User user = userDao.findByName(role.getUser().getName());
role.setUser(user);
Permission permission1 = new Permission();
permission1.setPermission("create");
permission1.setRole(role);
Permission permission2 = new Permission();
permission2.setPermission("update");
permission2.setRole(role);
List<Permission> permissions = new ArrayList<Permission>();
permissions.add(permission1);
permissions.add(permission2);
role.setPermissions(permissions);
roleDao.save(role);
return role;
} //查询用户通过用户名
@Override
public User findByName(String name) {
return userDao.findByName(name);
}
}

添加一个登录控制器,编写相关的接口。create接口添加了@RequiresPermissions("create"),用于进行权限注解测试。

LoginController.java

package com.louis.springboot.demo.controller;

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.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.louis.springboot.demo.model.Role;
import com.louis.springboot.demo.model.User;
import com.louis.springboot.demo.service.LoginService; @RestController
public class LoginController { @Autowired
private LoginService loginService; /**
* POST登录
* @param map
* @return
*/
@PostMapping(value = "/login")
public String login(@RequestBody User user) {
// 添加用户认证信息
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getName(), user.getPassword());
// 进行验证,这里可以捕获异常,然后返回对应信息
SecurityUtils.getSubject().login(usernamePasswordToken);
return "login ok!";
} /**
* 添加用户
* @param user
* @return
*/
@PostMapping(value = "/addUser")
public String addUser(@RequestBody User user) {
user = loginService.addUser(user);
return "addUser is ok! \n" + user;
} /**
* 添加角色
* @param role
* @return
*/
@PostMapping(value = "/addRole")
public String addRole(@RequestBody Role role) {
role = loginService.addRole(role);
return "addRole is ok! \n" + role;
} /**
* 注解的使用
* @return
*/
@RequiresRoles("admin")
@RequiresPermissions("create")
@GetMapping(value = "/create")
public String create() {
return "Create success!";
} @GetMapping(value = "/index")
public String index() {
return "index page!";
} @GetMapping(value = "/error")
public String error() {
return "error page!";
} /**
* 退出的时候是get请求,主要是用于退出
* @return
*/
@GetMapping(value = "/login")
public String login() {
return "login";
} @GetMapping(value = "/logout")
public String logout() {
return "logout";
}
}

添加一个MyShiroRealm并继承AuthorizingRealm,实现其中的两个方法。

doGetAuthenticationInfo:实现用户认证,通过服务加载用户信息并构造认证对象返回。

doGetAuthorizationInfo:实现权限认证,通过服务加载用户角色和权限信息设置进去。

MyShiroRealm.java

package com.louis.springboot.demo.config;

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.springframework.beans.factory.annotation.Autowired;
import com.louis.springboot.demo.model.Permission;
import com.louis.springboot.demo.model.Role;
import com.louis.springboot.demo.model.User;
import com.louis.springboot.demo.service.LoginService; /**
* 实现AuthorizingRealm接口用户用户认证
* @author Louis
* @date Jun 20, 2019
*/
public class MyShiroRealm extends AuthorizingRealm { @Autowired
private LoginService loginService; /**
* 用户认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
// 加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (authenticationToken.getPrincipal() == null) {
return null;
}
// 获取用户信息
String name = authenticationToken.getPrincipal().toString();
User user = loginService.findByName(name);
if (user == null) {
// 这里返回后会报出对应异常
return null;
} else {
// 这里验证authenticationToken和simpleAuthenticationInfo的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name,
user.getPassword().toString(), getName());
return simpleAuthenticationInfo;
}
} /**
* 角色权限和对应权限添加
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 获取登录用户名
String name = (String) principalCollection.getPrimaryPrincipal();
// 查询用户名称
User user = loginService.findByName(name);
// 添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for (Role role : user.getRoles()) {
// 添加角色
simpleAuthorizationInfo.addRole(role.getRoleName());
for (Permission permission : role.getPermissions()) {
// 添加权限
simpleAuthorizationInfo.addStringPermission(permission.getPermission());
}
}
return simpleAuthorizationInfo;
} }

添加一个Shiro配置类,主要配置路由的访问控制,以及注入自定义的认证器MyShiroRealm。

ShiroConfig.java

package com.louis.springboot.demo.config;

import java.util.HashMap;
import java.util.Map;
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.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class ShiroConfig { // 将自己的验证方式加入容器
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
return myShiroRealm;
} // 权限管理,配置主要是Realm的管理认证
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
} // Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterMap = new HashMap<String, String>();
// 登出
filterMap.put("/logout", "logout");
// swagger
filterMap.put("/swagger**/**", "anon");
filterMap.put("/webjars/**", "anon");
filterMap.put("/v2/**", "anon");
// 对所有用户认证
filterMap.put("/**", "authc");
// 登录
shiroFilterFactoryBean.setLoginUrl("/login");
// 首页
shiroFilterFactoryBean.setSuccessUrl("/index");
// 错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
} // 加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}

编译测试运行

1.  右键项目 -> Run as -> Maven install,开始执行Maven构建,第一次会下载Maven依赖,可能需要点时间,如果出现如下信息,就说明项目编译打包成功了。

2.  右键文件 DemoApplication.java -> Run as -> Java Application,开始启动应用,如果一开始数据库没有对应的表,在应用启动时会创建,我们可以通过控制台查看到对应的SQL语句。

3.  打开浏览器,访问:http://localhost:8080/swagger-ui.html,进入swagger接口文档界面。

4.  首先用MySQL客户端,打开数据库,往用户表里面插入一条记录,{id=1, name="admin", password="123"}。

然后试着用Swagger调用addUser往用户表插入一条记录。

{
"id": ,
"name": "xiaoming",
"password": ""
}

结果返回"error page!",这是因为我们没有登录,还没有操作权限。

接着调用POST的login接口,输入以下用户信息进行登录。

{
"name": "admin",
"password": ""
}

登录成功之后,返回“login ok!”信息。

再次调用addUser往用户表插入记录,发现记录已经可以成功插入了。

通过客户端工具我们也可以查看到记录已经插入进来了。

通过上面的测试,我们已经成功的验证了,受保护的接口需要在登录之后才允许访问。接下来我们来测试一下权限注解的效果,我们在create方法上加上了权限注解@RequiresPermissions("create"),表示用户需要拥有"create"的权限才能访问。

先尝试调用以下create接口,发现尽管我们已经登录了,依然因为没有权限返回了“error page!”。

然后我们调用addRole插入以下角色记录,这个角色关联了我们当前登录admin用户,且角色在创建时我们代码默认设置拥有了“create”权限。

{
"id": ,
"roleName": "admin",
"user": {
"name": "admin"
}
}

如果执行正确的话,会返回如下信息,说明角色已经成功插入了。

然后我们再一次调用create接口,因为此刻admin用户拥有admin角色,而admin角色拥有“create”权限,所以已经具有接口访问权限了。

参考资料

项目主页:http://shiro.apache.org/

W3C资料:https://www.w3cschool.cn/shiro/

百度百科:https://baike.baidu.com/item/shiro/17753571?fr=aladdin

相关导航

Spring Boot 系列教程目录导航

Spring Boot:快速入门教程

Spring Boot:整合Swagger文档

Spring Boot:整合MyBatis框架

Spring Boot:实现MyBatis分页

源码下载

码云:https://gitee.com/liuge1988/spring-boot-demo.git


作者:朝雨忆轻尘
出处:https://www.cnblogs.com/xifengxiaoma/
版权所有,欢迎转载,转载请注明原文作者及出处。

Spring Boot:整合Shiro权限框架的更多相关文章

  1. Spring boot整合shiro权限管理

    Apache Shiro功能框架: Shiro聚焦与应用程序安全领域的四大基石:认证.授权.会话管理和保密. #,认证,也叫作登录,用于验证用户是不是他自己所说的那个人: #,授权,也就是访问控制,比 ...

  2. 上手spring boot项目(二)之spring boot整合shiro安全框架

    题记:在学习了springboot和thymeleaf之后,想完成一个项目练练手,于是使用springboot+mybatis和thymeleaf完成一个博客系统,在完成的过程中出现的一些问题,将这些 ...

  3. Spring Boot 整合 Shiro ,两种方式全总结!

    在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro. 今天松哥就来和大家聊聊 Spring Boot ...

  4. Spring Boot2 系列教程(三十二)Spring Boot 整合 Shiro

    在 Spring Boot 中做权限管理,一般来说,主流的方案是 Spring Security ,但是,仅仅从技术角度来说,也可以使用 Shiro. 今天松哥就来和大家聊聊 Spring Boot ...

  5. spring boot整合shiro后,部分注解(Cache缓存、Transaction事务等)失效的问题

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/elonpage/article/details/78965176 前言 整合有缓存.事务的sprin ...

  6. Spring boot整合shiro框架

    ShiroConfiguration package com.energy.common.config; import java.util.LinkedHashMap; import java.uti ...

  7. SpringBoot整合Shiro权限框架实战

    什么是ACL和RBAC ACL Access Control list:访问控制列表 优点:简单易用,开发便捷 缺点:用户和权限直接挂钩,导致在授予时的复杂性,比较分散,不便于管理 例子:常见的文件系 ...

  8. spring boot整合shiro出现UnavailableSecurityManagerException

    spring boot自带spring security,spring security自然不用说是一个强大的安全框架,但是用惯了shiro,一时半会用不来spring security,所以要在sp ...

  9. SpringMVC整合Shiro权限框架

    尊重原创:http://blog.csdn.net/donggua3694857/article/details/52157313 最近在学习Shiro,首先非常感谢开涛大神的<跟我学Shiro ...

随机推荐

  1. CUDA线程协作之共享存储器“__shared__”&&“__syncthreads()”

    在GPU并行编程中,一般情况下,各个处理器都需要了解其他处理器的执行状态,在各个并行副本之间进行通信和协作,这涉及到不同线程间的通信机制和并行执行线程的同步机制. 共享内存"__share_ ...

  2. gdal1.10编译经验

    作者:朱金灿 来源:http://blog.csdn.net/clever101 集成了一些扩展库,使用makefile编译,出现了一个链接错误: libcmt.lib(crt0.obj): erro ...

  3. 签署 Centennial Program Addendum,使用 Desktop Bridge 将 Win32 应用转制成 UWP

    原文 签署 Centennial Program Addendum,使用 Desktop Bridge 将 Win32 应用转制成 UWP 能上架 Windows 应用商店的并不一定必须是 UWP 应 ...

  4. 创建一个显示所有预定义系统颜色的ListBox

    原文 Creating a ListBox that Shows All Predefined System Colors 该System.Windows.SystemColors类包含了一系列揭露当 ...

  5. OpenGL(十四) 模板测试

    启用模板测试时,OpenGL会在内存中开辟一块空间作为模板缓冲区,里边保存了每个像素的"模板值",模板测试的过程就是把每一个像素的模板值与一个设定的模板参考值进行比较,符合设定条件 ...

  6. 升级phpstudy2018默认mysql版本到5.7

    原文:升级phpstudy2018默认mysql版本到5.7 版权声明:在那最初的相遇中,我们都曾经为彼此心动过... https://blog.csdn.net/weixin_36185028/ar ...

  7. Windows系统CPU内存网络性能统计第一篇 内存

    最近翻出以前做过的Windows系统性能统计程序,这个程序可以统计系统中的CPU使用情况,内存使用情况以及网络流量.现在将其整理一下(共有三篇),希望对大家有所帮助. 目录如下: 1.<Wind ...

  8. xadmin下设置“use_bootswatch = True”无效解决方法

    from xadmin import viewsimport xadmin class BaseSetting(object): enable_themes=True use_bootswatch=T ...

  9. wpf的webbrowser与javascript交互

    JS调用C#代码 HTML代码: <button onclick="window.external.Test('called from script code')"> ...

  10. 天气预报API接口

    原文:天气预报API接口 一.中央气象台API接口: 1. XML接口 http://flash.weather.com.cn/wmaps/xml/china.xml 这个是全国天气的根节点,列出所有 ...