Spring Boot:整合Shiro權限框架

綜合概述

Shiro是Apache旗下的一個開源項目,它是一個很是易用的安全框架,提供了包括認證、受權、加密、會話管理等功能,與Spring Security同樣屬基於權限的安全框架,可是與Spring Security 相比,Shiro使用了比較簡單易懂易於使用的受權方式。Shiro屬於輕量級框架,相對於Spring Security簡單不少,並無security那麼複雜。html

優點特色

它是一個功能強大、靈活的、優秀的、開源的安全框架。java

它能夠勝任身份驗證、受權、企業會話管理和加密等工做。mysql

它易於使用和理解,與Spring Security相比,入門門檻低。git

主要功能

  • 驗證用戶身份
  • 用戶訪問權限控制
  • 支持單點登陸(SSO)功能
  • 能夠響應認證、訪問控制,或Session事件
  • 支持提供「Remember Me」服務
  • .......

框架體系

Shiro 的總體框架大體以下圖所示(圖片來自互聯網):web

Authentication(認證), Authorization(受權), Session Management(會話管理), Cryptography(加密)表明Shiro應用安全的四大基石。算法

它們分別是:spring

  • Authentication(認證):用戶身份識別,一般被稱爲用戶「登陸」。
  • Authorization(受權):訪問控制。好比某個用戶是否具備某個操做的使用權限。
  • Session Management(會話管理):特定於用戶的會話管理,甚至在非web 應用程序。
  • Cryptography(加密):在對數據源使用加密算法加密的同時,保證易於使用。

除此以外,還有其餘的功能來支持和增強這些不一樣應用環境下安全領域的關注點。sql

特別是對如下的功能支持:數據庫

  • Web支持:Shiro 提供的 web 支持 api ,能夠很輕鬆的保護 web 應用程序的安全。
  • 緩存:緩存是 Apache Shiro 保證安全操做快速、高效的重要手段。
  • 併發:Apache Shiro 支持多線程應用程序的併發特性。
  • 測試:支持單元測試和集成測試,確保代碼和預想的同樣安全。
  • 「Run As」:這個功能容許用戶在許可的前提下假設另外一個用戶的身份。
  • 「Remember Me」:跨 session 記錄用戶的身份,只有在強制須要時才須要登陸。

主要流程

在概念層,Shiro 架構包含三個主要的理念:Subject, SecurityManager 和 Realm。下面的圖展現了這些組件如何相互做用,咱們將在下面依次對其進行描述。apache

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.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.louis.springboot</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-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.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</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.1</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: 8080
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: 123456
  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": 2,
  "name": "xiaoming",
  "password": "123"
}

結果返回"error page!",這是由於咱們沒有登陸,尚未操做權限。

接着調用POST的login接口,輸入如下用戶信息進行登陸。

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

登陸成功以後,返回「login ok!」信息。

再次調用addUser往用戶表插入記錄,發現記錄已經能夠成功插入了。

經過客戶端工具咱們也能夠查看到記錄已經插入進來了。

經過上面的測試,咱們已經成功的驗證了,受保護的接口須要在登陸以後才容許訪問。接下來咱們來測試一下權限註解的效果,咱們在create方法上加上了權限註解@RequiresPermissions("create"),表示用戶須要擁有"create"的權限才能訪問。

先嚐試調用如下create接口,發現儘管咱們已經登陸了,依然由於沒有權限返回了「error page!」。

而後咱們調用addRole插入如下角色記錄,這個角色關聯了咱們當前登陸admin用戶,且角色在建立時咱們代碼默認設置擁有了「create」權限。

{
  "id": 1,
  "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/ 
版權全部,歡迎轉載,轉載請註明原文做者及出處。

相關文章
相關標籤/搜索