Shiro之注解篇

1、功能实现

1.开启注解功能,使用并比较注解
2.解决注解式,登录页和无权访问页面不跳转问题
3.拦截器跟注解同时使用的执行顺序

2、shiro03子工程

本篇以 记住我篇 为基础
在这里插入图片描述

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.yzm</groupId>
        <artifactId>shiro</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
    </parent>

    <artifactId>shiro03</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>shiro03</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        <dependency>
            <groupId>com.yzm</groupId>
            <artifactId>common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.168.192.128:3306/testdb2?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
    username: root
    password: 1234

mybatis-plus:
  mapper-locations: classpath:/mapper/*Mapper.xml
  type-aliases-package: com.yzm.shiro03.entity
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3、认证和授权

package com.yzm.shiro02.config;

import com.yzm.shiro02.entity.Permissions;
import com.yzm.shiro02.entity.Role;
import com.yzm.shiro02.entity.User;
import com.yzm.shiro02.service.PermissionsService;
import com.yzm.shiro02.service.RoleService;
import com.yzm.shiro02.service.UserService;
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 java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 自定义Realm,实现认证和授权
 * AuthorizingRealm 继承 AuthorizingRealm
 * AuthorizingRealm 提供 授权方法 doGetAuthorizationInfo
 * AuthorizingRealm 提供 认证方法 doGetAuthenticationInfo
 */
public class MyShiroRealm extends AuthorizingRealm {

    private final UserService userService;
    private final RoleService roleService;
    private final PermissionsService permissionsService;

    public MyShiroRealm(UserService userService, RoleService roleService, PermissionsService permissionsService) {
        this.userService = userService;
        this.roleService = roleService;
        this.permissionsService = permissionsService;
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) principalCollection.getPrimaryPrincipal();
        // 查询用户,获取角色ids
        User user = userService.lambdaQuery().eq(User::getUsername, username).one();
        List<Integer> roleIds = Arrays.stream(user.getRIds().split(","))
                .map(Integer::parseInt)
                .collect(Collectors.toList());

        // 查询角色,获取角色名、权限ids
        List<Role> roles = roleService.listByIds(roleIds);
        Set<String> roleNames = new HashSet<>(roles.size());
        Set<Integer> permIds = new HashSet<>();
        roles.forEach(role -> {
            roleNames.add(role.getRName());
            Set<Integer> collect = Arrays.stream(
                    role.getPIds().split(",")).map(Integer::parseInt).collect(Collectors.toSet());
            permIds.addAll(collect);
        });

        // 获取权限名称
        List<Permissions> permissions = permissionsService.listByIds(permIds);
        List<String> permNames = permissions.stream().map(Permissions::getPName).collect(Collectors.toList());

        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addRoles(roleNames);
        authorizationInfo.addStringPermissions(permNames);
        return authorizationInfo;
    }

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 获取用户名跟密码
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        String username = usernamePasswordToken.getUsername();

        // 查询用户是否存在
        User user = userService.lambdaQuery().eq(User::getUsername, username).one();
        if (user == null) {
            throw new UnknownAccountException();
        }

        return new SimpleAuthenticationInfo(
                user.getUsername(),
                user.getPassword(),
                // 用户名 + 盐
                ByteSource.Util.bytes(user.getUsername() + user.getSalt()),
                getName()
        );
    }
}

4、ShiroConfig 配置类

package com.yzm.shiro03.config;

import com.yzm.shiro03.service.PermissionsService;
import com.yzm.shiro03.service.RoleService;
import com.yzm.shiro03.service.UserService;
import com.yzm.shiro03.utils.EncryptUtils;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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.filter.authc.LogoutFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

@Configuration
public class ShiroConfig {

    private final UserService userService;
    private final RoleService roleService;
    private final PermissionsService permissionsService;

    public ShiroConfig(UserService userService, RoleService roleService, PermissionsService permissionsService) {
        this.userService = userService;
        this.roleService = roleService;
        this.permissionsService = permissionsService;
    }

    /**
     * 凭证匹配器
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName(EncryptUtils.ALGORITHM_NAME);
        hashedCredentialsMatcher.setHashIterations(EncryptUtils.HASH_ITERATIONS);
        return hashedCredentialsMatcher;
    }

    /**
     * 自定义Realm
     */
    @Bean
    public MyShiroRealm shiroRealm() {
        MyShiroRealm shiroRealm = new MyShiroRealm(userService, roleService, permissionsService);
        shiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return shiroRealm;
    }

    /**
     * 记住我功能
     */
    @Bean
    public Cookie simpleCookie() {
        SimpleCookie cookie = new SimpleCookie("rememberMe");
        //设为true后,只能通过http访问,javascript无法访问
        //防止xss读取cookie
        cookie.setHttpOnly(true);
        cookie.setPath("/");
        //存活时间,单位秒;-1表示关闭浏览器该cookie失效
        cookie.setMaxAge(120);
        return cookie;
    }

    @Bean
    public CookieRememberMeManager rememberMeManager() {
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        rememberMeManager.setCookie(simpleCookie());
        //cookie加密的密钥
        rememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
        return rememberMeManager;
    }

    /**
     * 安全管理SecurityManager
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 配置realm
        securityManager.setRealm(shiroRealm());
        // 记住我功能
        securityManager.setRememberMeManager(rememberMeManager());
        return securityManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter() {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager());
        shiroFilterFactoryBean.setLoginUrl("/login"); // 登录页url,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
        shiroFilterFactoryBean.setUnauthorizedUrl("/401"); // 访问无权限跳转url

        return shiroFilterFactoryBean;
    }
}

5、注解使用

在ShiroConfig中添加如下内容

	/**
     * 开启注解方式控制访问url
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
        return authorizationAttributeSourceAdvisor;
    }
@RequiresRoles 等同于 roles
@RequiresPermissions 等同于 perms
@RequiresAuthentication 等同于 authc
@RequiresUser 等同于 user
@RequiresGuest@RequiresUser 完全相反,即未登录也不能使用记住我功能,只能是游客

HomeController
修改登录接口,进行登录成功或失败重定向
自定义退出接口,不使用Shiro默认的
新增3个接口

package com.yzm.shiro03.controller;

import com.yzm.shiro03.entity.User;
import com.yzm.shiro03.service.UserService;
import com.yzm.shiro03.utils.EncryptUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresGuest;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HomeController {

    private final UserService userService;

    public HomeController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping(value = {"/", "/home"})
    public String home(ModelMap map) {
        Subject subject = SecurityUtils.getSubject();
        map.addAttribute("subject", subject.getPrincipals());
        return "home";
    }

    @GetMapping("login")
    public String login() {
        return "login";
    }

    @GetMapping("401")
    public Object notRole() {
        return "401";
    }

    @PostMapping("register")
    public Object register(ModelMap map, @RequestParam String username, @RequestParam String password) {
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        // 密码加密
        EncryptUtils.encryptPassword(user);
        userService.save(user);
        map.addAttribute("user", user);
        return "home";
    }

    @PostMapping("login")
    public Object login(@RequestParam String username, @RequestParam String password, boolean rememberMe) {
        // 1.创建UsernamePasswordToken
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
        // 使用记住我功能
        usernamePasswordToken.setRememberMe(rememberMe);
        // 2.创建Subject 用户主体
        Subject subject = SecurityUtils.getSubject();

        String url = "/home";
        try {
            // 3.前期准备后,开始登录
            subject.login(usernamePasswordToken);
        } catch (IncorrectCredentialsException e) {
            url = "/login?failure";
        } catch (AuthenticationException e) {
            url = "/login";
        }
        return "redirect:" + url;
    }

    @PostMapping("/logout")
    public Object logout() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated() || subject.isRemembered()) {
            subject.logout();
        }
        return "redirect:/login";
    }

	@GetMapping("requiresGuest")
    @RequiresGuest 
    @ResponseBody
    public Object requiresGuest() {
        return "requiresGuest";
    }

    @GetMapping("requiresAuthentication")
    @RequiresAuthentication
    @ResponseBody
    public Object requiresAuthentication() {
        return "requiresAuthentication";
    }

    @GetMapping("requiresUser")
    @RequiresUser
    @ResponseBody
    public Object requiresUser() {
        return "requiresUser";
    }
}

UserController、AdminController 使用注解控制权限访问

package com.yzm.shiro03.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/admin")
@RequiresRoles("ADMIN")
public class AdminController {

    @GetMapping
    public Object admin() {
        return SecurityUtils.getSubject().getPrincipal();
    }

    @GetMapping("select")
    @RequiresPermissions("admin:select")
    public Object select() {
        return "Select";
    }

    @GetMapping("create")
    @RequiresPermissions("admin:create")
    public Object create() {
        return "Create";
    }

    @GetMapping("update")
    @RequiresPermissions("admin:update")
    public Object update() {
        return "Update";
    }

    @GetMapping("delete")
    @RequiresPermissions("admin:delete")
    public Object delete() {
        return "Delete";
    }
}
package com.yzm.shiro03.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("//user")
@RequiresRoles(value = {"USER", "ADMIN"}, logical = Logical.OR)
    public class UserController {

    @GetMapping
    public Object user() {
        return SecurityUtils.getSubject().getPrincipal();
    }

    @GetMapping("select")
    @RequiresPermissions("user:select")
    public Object select() {
        return "Select";
    }

    @GetMapping("create")
    @RequiresPermissions("user:create")
    public Object create() {
        return "Create";
    }

    @GetMapping("update")
    @RequiresPermissions("user:update")
    public Object update() {
        return "Update";
    }

    @GetMapping("delete")
    @RequiresPermissions("user:delete")
    public Object delete() {
        return "Delete";
    }

    @GetMapping("createAndUpdate")
    //需要同时拥有
    @RequiresPermissions(value = {"user:create", "user:update"}, logical = Logical.AND)
    public Object createAndUpdate() {
        return "Create And Update";
    }

    @GetMapping("createOrUpdate")
    //拥有其中任意一个即可
    @RequiresPermissions(value = {"user:create", "user:update"}, logical = Logical.OR)
    public Object createOrUpdate() {
        return "Create Or Update";
    }
}

6、html页面

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>当前登录状态:<span th:text="${subject == null ? '未登录 ' : '已登录'}"></span></h1>

<h2>1.注册 <span th:if="${user != null}"> [[${user.username}]] 成功</span></h2>
<form action="/register" method="post">
    <p>
        <label for="username">Username</label>
        <input type="text" id="username" name="username" placeholder="Username">
    </p>
    <p>
        <label for="password">Password</label>
        <input type="password" id="password" name="password" placeholder="Password">
    </p>
    <button type="submit">Register</button>
</form>

<h2>2.注销</h2>
<form action="/logout" method="post">
    <button type="submit">Sign out</button>
</form>

<h3>3.User 接口列表</h3>
<h4>
    <a href="/user">User角色</a>
</h4>
<p><a href="/user/select">User角色,拥有 select 权限</a></p>
<p><a href="/user/create">User角色,拥有 create 权限</a></p>
<p><a href="/user/update">User角色,拥有 update 权限</a></p>
<p><a href="/user/delete">User角色,拥有 delete 权限</a></p>
<p><a href="/user/createAndUpdate">User角色,拥有 create and update 权限</a></p>

<h3>4.Admin 接口列表</h3>
<h4>
    <a href="/admin">Admin角色</a>
</h4>
<p><a href="/admin/select">Admin角色,拥有 select 权限</a></p>
<p><a href="/admin/create">Admin角色,拥有 create 权限</a></p>
<p><a href="/admin/update">Admin角色,拥有 update 权限</a></p>
<p><a href="/admin/delete">Admin角色,拥有 delete 权限</a></p>

<h3>注解比较</h3>
<p><a href="/requiresGuest">@RequiresGuest 注解</a></p>
<p><a href="/requiresAuthentication">@RequiresAuthentication 注解</a></p>
<p><a href="/requiresUser">@RequiresUser 注解</a></p>

</body>
</html>

login.html、401.html 参考上一篇

7、测试页面跳转

启动项目,访问/home,未登录,点击user
在这里插入图片描述
页面报错,并且控制台打印错误信息
在这里插入图片描述
shiroFilterFactoryBean.setLoginUrl("/login");
这行代码不起作用了,先不理它,一会解决

访问/login 登录yzm,跳转到主页,点击Admin角色
在这里插入图片描述
在这里插入图片描述
跟上面一样页面报错,控制台打印错误信息
在这里插入图片描述
shiroFilterFactoryBean.setUnauthorizedUrl("/401"); 一样无效
这是因为注解模式下,登录失败与没有权限都是通过抛出异常,并且默认没有去处理或者捕获这些异常。
有两种解决方案

第一种:设置全局捕获

package com.yzm.shiro03.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Shiro注解模式下,登录失败与没有权限都是通过抛出异常,并且默认并没有去处理或者捕获这些异常。
 * 解决方式,通过自定义全局异常捕获处理
 */
@Slf4j
@RestControllerAdvice
public class MyExceptionHandler {

    @ExceptionHandler
    public void ErrorHandler(AuthorizationException e, HttpServletRequest request, HttpServletResponse response) throws IOException {
        log.error("注解方式,自定义异常捕获");
        if (e instanceof UnauthenticatedException) {
            // 重定向
            WebUtils.issueRedirect(request, response, "/login");
        } else if (e instanceof UnauthorizedException) {
            WebUtils.issueRedirect(request, response, "/401");
        }
    }
}

重启项目,未登录访问 User角色 跳转到登录页
在这里插入图片描述
登录yzm,访问 Admin 角色,跳转到无权页面
在这里插入图片描述

第二种:通过在SpringMVC下配置捕获相应异常
在ShiroConfig中,添加

	/**
     * 问题:未登录不会自动跳转到登录页、无权访问页面不跳转
     * 原因:Shiro注解模式下,登录失败与没有权限都是通过抛出异常,并且默认并没有去处理或者捕获这些异常。
     * 解决:通过在SpringMVC下配置捕获相应异常来通知用户信息
     */
    @Bean
    public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver simpleMappingExceptionResolver = new SimpleMappingExceptionResolver();
        Properties properties = new Properties();
        // 未登录访问接口跳转到/login、登录后没有权限跳转到/401
        properties.setProperty("org.apache.shiro.authz.UnauthenticatedException", "redirect:/login");
        properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "redirect:/401");
        simpleMappingExceptionResolver.setExceptionMappings(properties);
        return simpleMappingExceptionResolver;
    }

注意:
1.使用的是重定向:“redirect:/login”;而不是转发:"/login",使用转发的话,能跳转到登录页,但表单提交会报错
在这里插入图片描述
在这里插入图片描述
改回properties.setProperty(“org.apache.shiro.authz.UnauthenticatedException”, “redirect:/login”);
2.注释掉全局捕获 以免影响第二种方法的测试
在这里插入图片描述
重启项目,测试结果跟第一种一样

8、注解比较

在这里插入图片描述

已登录,未记住我,重开浏览器之后,就成了未登录
@RequiresGuest:未登录可以访问;认证过或使用记住我功能拒绝访问
@RequiresAuthentication: 认证过可以访问,其他时候拒绝访问
@RequiresUser: 认证过或使用记住我功能可以访问
@RequiresPermissions(value = {“user:create”, “user:update”}, logical = Logical.AND)
同时具备2个权限才能访问
@RequiresPermissions(value = {“user:create”, “user:update”}, logical = Logical.OR)
拥有其中任意一个权限就可以访问
@RequiresRoles 跟 @RequiresPermissions 使用差不多的

9、自定义错误页面

在ShiroConfig中,添加

/**
     * 自定义错误页面
     */
    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
        return factory -> {
        	// 这种可以进行转发,但在处理跳转到登录页之后,进行提交效果不好,这里知道就行
        	//ErrorPage errorLoginPage = new ErrorPage(UnauthenticatedException.class, "/login");
            //ErrorPage error401Page = new ErrorPage(UnauthorizedException.class, "/401");
            ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/401");
            ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/404");
            ErrorPage error500Page = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/500");
            factory.addErrorPages(error401Page, error404Page, error500Page);
        };
    }

在HomeController 新增接口

	@GetMapping("/fail")
    @ResponseBody
    public Object fail() {
        int i = 1/0;
        return "出错了";
    }

    @GetMapping("404")
    public Object notFound() {
        return "404";
    }

    @GetMapping("500")
    public Object error() {
        return "500";
    }

新增404、500页面,内容跟401差不多

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>500</title>
</head>
<body>
<h1>服务器崩溃了</h1>
</body>
</html>

重启,访问/fail 跳转到500页面,访问不存在的url跳转到404页面

10、注解跟拦截器同时使用,拦截器优先

例如:在ShiroConfig#shiroFilter中,对/user/** 进行roles[ADMIN]拦截

    @Bean
    public ShiroFilterFactoryBean shiroFilter() {
        ...

        Map<String, String> definitionMap = new LinkedHashMap<>();
        definitionMap.put("/user/**", "roles[ADMIN]");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(definitionMap);
        return shiroFilterFactoryBean;
    }

debug role注解处理器和role拦截器

在这里插入图片描述
在这里插入图片描述

重启,登录yzm,访问/user,先进的是拦截器,但拦截器配置的需要admin角色,yzm只有user角色
所以直接跳转到401页面,不再继续注解处理器

在这里插入图片描述

如果拦截器通过,就还会继续注解处理器,只有都通过才能访问

相关链接

首页
上一篇:记住我篇
下一篇:缓存篇

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值