SpringSecurity(3)SpringBoot、JSP、MyBatis整合进行认证和授权

技术选型

SpringBoot2.1.3,SpringSecurity,MySQL,mybatis,jsp

下面的三个版本是层次递进的。

1、初步整合认证第一版

这个版本中我们不自定义jsp页面,同时也不连接数据库,看看在SpringBoot中,加入了Spring Security之后有什么效果:

1.1 创建工程,导入jar包

创建一个project,当作一个父工程,只是为了把相关的东西放到一个目录下面,接下来就在这个里面创建子模块:

在这里插入图片描述

父工程中可以删掉src目录;

在父工程下面创建一个module:springboot_security_jsp,用于本次项目:

在这里插入图片描述

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>
    <artifactId>springboot_security_jsp</artifactId>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

1.2 创建启动类

package com.zdwhong;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author ZDW
 * @create 2020-07-18 21:24
 */
@SpringBootApplication
public class SecurityJspApplication {
    public static void main(String[] args) {
        SpringApplication.run(SecurityJspApplication.class,args);
    }
}

1.3 创建controller

package com.zdwhong.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author ZDW
 * @create 2020-07-18 21:30
 */
@Controller
@RequestMapping("product")
public class ProductController {

    @RequestMapping
    @ResponseBody  //返回json数据,不进行视图解析器
    public String findAll() {
        return "success";
    }
}

1.4 启动工程,测试

其实上面在这个过程,也是SpringBoot工程快速搭建的过程

浏览器访问:http://127.0.0.1:8080/product 可以看到页面显示 success ,即表示成功了。

1.5 加入Security依赖

在pom.xml中添加下面的依赖:

 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-security</artifactId>
</dependency>

1.6 重启项目,测试

SpringBoot项目中,只要加入了SpringSecurity的依赖之后,那么不用配置,就已经具有了权限控制效果:

启动成功,浏览器再次访问:http://127.0.0.1:8080/product 就会自动跳转到 http://127.0.0.1:8080/login 登录页面:

在这里插入图片描述

这个登录页并不是我们写的,毕竟我们都还没写任何页面,

那么问题来了!此刻并没有连接数据库,也并未在内存中指定认证用户,如何认证呢?

其实SpringBoot已经提供了默认的用户名:user,密码是在控制台有打印:

Using generated security password: e1559170-e5e6-422f-96a5-a724e03ea1fb

e1559170-e5e6-422f-96a5-a724e03ea1fb 这个密码是随机生成的。

输入用户名和密码登录之后,照样能看到页面显示 success

2、整合认证第二版**【加入jsp使用自定义认证页面】**

注意:SpringBoot官方是不推荐在SpringBoot中使用jsp的,那么到底可以使用吗?答案是肯定的!

不过需要导入tomcat插件启动项目,不能再用SpringBoot默认tomcat了。

2.1 导入tomcat插件

因为要使用jsp页面,所以启动项目的时候不能通过运行启动类执行,因为默认是不支持jsp页面的。所以需要导入tomcat的插件,来进行项目的启动:

<!--集成jsp页面需要tomcat插件-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!--集成jsp页面需要tomcat插件-->

2.2 加入jsp等静态资源

在src/main目录下创建webapp目录

在这里插入图片描述

这时webapp目录并不能正常使用,因为只有web工程才有webapp目录,在pom文件中修改项目为web工程

<packaging>war</packaging>

在这里插入图片描述

这时webapp目录,可以正常使用了!

静态资源可以参考之前的课程:注意WEB-INF目录就不用了哈!

2.3 修改login.jsp中认证的url地址

在这里插入图片描述

2.4 修改header.jsp中退出登录的url地址

在这里插入图片描述

2.5 编写Spring Security配置类

编写自定义的配置类,需要添加注解:@EnableWebSecurity,并继承:WebSecurityConfigurerAdapter 或者实现接口:WebSecurityConfigurer

package com.zdwhong.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /*** 这里先不连接数据库了 */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //在内存中配置用户信息
        auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}123")
                .roles("USER");
    }

    //SpringSecurity配置信息
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //表示对静态资源和登录登出页面放行
                .antMatchers("/login.jsp", "failer.jsp", "/css/**", "/img/**", "/plugins/**").permitAll()
                //表示/product需要USER角色
                .antMatchers("/product").hasAnyRole("USER")
                //表示其他的任意请求都是需要先登录才能访问
                .anyRequest().authenticated()
                //用and连接下一个配置
                .and()
                //表示是form表单登录
                .formLogin()
                //指定登录页面
                .loginPage("/login.jsp")
                //指定登录的处理器路径
                .loginProcessingUrl("/login")
                //指定登录成功的默认跳转路径
                .successForwardUrl("/index.jsp")
                //指定登录失败的默认跳转路径
                .failureForwardUrl("/failer.jsp")
                .and()
                //指定登出
                .logout()
                //指定登出的路径
                .logoutSuccessUrl("/logout")
                //指定登出之后清除session
                .invalidateHttpSession(true)
                //指定登录之后跳转到登录页面
                .logoutSuccessUrl("/login.jsp")
                .and()
                //配置csrf跨站请求伪造是关闭的,所以存在跨站请求伪造的危险
                .csrf()
                .disable();
    }
}

2.6 修改ProductController

package com.zdwhong.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author ZDW
 * @create 2020-07-18 21:30
 */
@Controller
@RequestMapping("product")
public class ProductController {

    @RequestMapping("/findAll")
    //@ResponseBody  //返回json数据,不进行视图解析器
    public String findAll() {
        //return "success";

        //经过视图解析器,跳转到product-list.jsp页面
        return "product-list";
    }
}

2.7 配置视图解析器

创建application.yml文件,配置jsp的视图解析器:

spring:
  mvc:
    view:
      prefix: /pages/
      suffix: .jsp

2.8 使用tomcat插件启动项目

要使用jsp页面,就不能执行主启动类来启动项目,需要配置tomcat插件的执行命令:

Edit Configurations配置:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

配置成功之后,启动,浏览器访问:http://127.0.0.1:8080/

会跳转到我们自己的login.jsp页面:

在这里插入图片描述

输入我们在WebSecurityConfig中配置的user/123就能登录,认证完成了。

3、整合认证第三版【连接数据库认证】

3.1 数据库环境准备

创建数据库(这里使用的和之前的是一样的):spring_security,建表sql如下:

CREATE DATABASE /*!32312 IF NOT EXISTS*/`spring_security` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;

USE `spring_security`;

DROP TABLE IF EXISTS `persistent_logins`;

CREATE TABLE `persistent_logins` (
  `username` varchar(64) NOT NULL,
  `series` varchar(64) NOT NULL,
  `token` varchar(64) NOT NULL,
  `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `sys_permission`;

CREATE TABLE `sys_permission` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `permission_NAME` varchar(30) DEFAULT NULL COMMENT '菜单名称',
  `permission_url` varchar(100) DEFAULT NULL COMMENT '菜单地址',
  `parent_id` int(11) NOT NULL DEFAULT '0' COMMENT '父菜单id',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

insert  into `sys_permission`(`ID`,`permission_NAME`,`permission_url`,`parent_id`) values (1,'deleteProduct','/product/deleteById',0),(2,'getByProductId','/product/getByProductId',0);

DROP TABLE IF EXISTS `sys_role`;

CREATE TABLE `sys_role` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `ROLE_NAME` varchar(30) DEFAULT NULL COMMENT '角色名称',
  `ROLE_DESC` varchar(60) DEFAULT NULL COMMENT '角色描述',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

insert  into `sys_role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (8,'ROLE_USER','普通角色'),(9,'ROLE_PRODUCT','产品管理');

DROP TABLE IF EXISTS `sys_role_permission`;

CREATE TABLE `sys_role_permission` (
  `RID` int(11) NOT NULL COMMENT '角色编号',
  `PID` int(11) NOT NULL COMMENT '权限编号',
  PRIMARY KEY (`RID`,`PID`),
  KEY `FK_Reference_12` (`PID`),
  CONSTRAINT `FK_Reference_11` FOREIGN KEY (`RID`) REFERENCES `sys_role` (`ID`),
  CONSTRAINT `FK_Reference_12` FOREIGN KEY (`PID`) REFERENCES `sys_permission` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `sys_role_permission`(`RID`,`PID`) values (9,1);

DROP TABLE IF EXISTS `sys_user`;

CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用户名称',
  `password` varchar(120) NOT NULL COMMENT '密码',
  `status` int(1) DEFAULT '1' COMMENT '1开启0关闭',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

insert  into `sys_user`(`id`,`username`,`password`,`status`) values (4,'admin','$2a$10$uSzYVcICU0gbqPMSc9CAv.atpIS2i/95mYWx7EuUn1bEfAIII6RZi',1),(5,'xiaoming','$2a$10$uSzYVcICU0gbqPMSc9CAv.atpIS2i/95mYWx7EuUn1bEfAIII6RZi',1),(6,'xiaoma','$2a$10$uSzYVcICU0gbqPMSc9CAv.atpIS2i/95mYWx7EuUn1bEfAIII6RZi',1),(7,'lisi','$2a$10$LaWqEF27Fdr.J19Wtd/WGu3SR0CVZhjAdVyzR7lvhUsbma88NX7rG',1),(11,'wangwu','$2a$10$DBsVodOx4buEEjEx4Lli8OWoIpJOj2.hRBqgroWP.MGWRFPkZq10K',0);

DROP TABLE IF EXISTS `sys_user_role`;

CREATE TABLE `sys_user_role` (
  `UID` int(11) NOT NULL COMMENT '用户编号',
  `RID` int(11) NOT NULL COMMENT '角色编号',
  PRIMARY KEY (`UID`,`RID`),
  KEY `FK_Reference_10` (`RID`),
  CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `sys_role` (`ID`),
  CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `sys_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

insert  into `sys_user_role`(`UID`,`RID`) values (5,8),(6,8),(5,9);

3.2 导入数据库操作相关jar包

pom.xml中加入下面的依赖:

<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>
<!--通用mapper-->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.5</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.8</version>
</dependency>

3.3 修改application.yml

修改application.yml,添加数据库连接相关配置:

server:
  port: 8080
spring:
  mvc:
    view:
      prefix: /pages/
      suffix: .jsp
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.56.102/spring_security?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false
    username: root
    password: 123456
mybatis:
  type-aliases-package: com.zdwhong.domain
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    com.itheima: debug

3.4 启动类添加mapper扫描

@SpringBootApplication
@MapperScan("com.zdwhong.mapper")  //mapper扫描
public class SecurityJspApplication {
    public static void main(String[] args) {
        SpringApplication.run(SecurityJspApplication.class,args);
    }
}

3.5 创建pojo对象

3.5.1 创建角色pojo对象SysRole

实现:GrantedAuthority,重写getAuthority方法,返回roleName,这样我们使用角色的时候,直接使用我们的SysRole即可。

package com.zdwhong.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;

/**
 * @author ZDW
 * @create 2020-07-19 15:43
 */
@Data
public class SysRole implements GrantedAuthority {

    private Integer id;
    private String roleName;
    private String roleDesc;

    //标记此属性不做json处理
    @JsonIgnore
    @Override
    public String getAuthority() {
        return roleName;
    }
}

3.5.2 创建用户pojo对象SysUser

这里直接实现SpringSecurity的用户对象接口,并添加角色集合私有属性。

注意接口属性都要标记不参与json的处理。

package com.zdwhong.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author ZDW
 * @create 2020-07-19 15:49
 */
@Data
public class SysUser implements UserDetails {

    private Integer id;
    private String username;
    private String password;
    private Integer status;
    private List<SysRole> roles = new ArrayList<>();

    @JsonIgnore
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return roles;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isEnabled() {
        return true;
    }
}

3.6 编写mapper接口

3.6.1 RoleMapper

package com.zdwhong.mapper;

import com.zdwhong.domain.SysRole;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

/**
 * @author ZDW
 * @create 2020-07-19 15:53
 */
public interface RoleMapper extends Mapper<SysRole> {
    /**
     * 根据用户ID查询对应的角色信息
     * @param uid
     * @return
     */
    @Select("SELECT r.id, r.role_name roleName, r.role_desc roleDesc "
            + "FROM sys_role r, sys_user_role ur "
            + "WHERE r.id=ur.rid AND ur.uid=#{uid}")
    public List<SysRole> findByUid(Integer uid);
}

3.6.2 UserMapper

package com.zdwhong.mapper;

import com.zdwhong.domain.SysUser;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

/**
 * @author ZDW
 * @create 2020-07-19 15:54
 */
@Component
public interface UserMapper extends Mapper<SysUser> {
    /**
     * 根据用户名称查询用户信息以及用户对应的角色信息
     * @param username
     * @return
     */
    @Select("select * from sys_user where username=#{username}") 
    @Results({@Result(id = true, property = "id", column = "id"), 
            @Result(property = "roles", column = "id", javaType = List.class, 
                    many = @Many(select = "com.zdwhong.mapper.RoleMapper.findByUid")) 
    })
    public SysUser findByUsername(String username);
}

3.7 提供UserDetailsService认证接口实现

我们现在应该知道,Spring Security认证是通过UserDetailsService的loadUserByUsername方法去实现的,所以我们要让自己的service实现这个方法:

UserService:

package com.zdwhong.service;

import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * @author ZDW
 * @create 2020-07-19 15:58
 */
public interface UserService extends UserDetailsService {
}

UserServiceImpl:

package com.zdwhong.service.impl;

import com.zdwhong.mapper.UserMapper;
import com.zdwhong.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author ZDW
 * @create 2020-07-19 15:59
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //调用userMapper的根据用户名查询用户信息的方法,返回的对象即是UserDetails类型
        return userMapper.findByUsername(s);
    }
}

3.8 修改配置类

package com.zdwhong.config;

import com.zdwhong.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    /**
     * 把加密对象放入IOC容器中
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /*** 使用数据库中的用户 */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //在内存中配置用户信息
        /*auth.inMemoryAuthentication()
                .withUser("user")
                .password("{noop}123")
                .roles("USER");*/
        //配置自定义的用户信息
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    //SpringSecurity配置信息
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //表示对静态资源和登录登出页面放行
                .antMatchers("/login.jsp", "failer.jsp", "/css/**", "/img/**", "/plugins/**").permitAll()
                //表示/product需要USER角色
                .antMatchers("/product").hasAnyRole("USER")
                //表示其他的任意请求都是需要先登录才能访问
                .anyRequest().authenticated()
                //用and连接下一个配置
                .and()
                //表示是form表单登录
                .formLogin()
                //指定登录页面
                .loginPage("/login.jsp")
                //指定登录的处理器路径
                .loginProcessingUrl("/login")
                //指定登录成功的默认跳转路径
                .successForwardUrl("/index.jsp")
                //指定登录失败的默认跳转路径
                .failureForwardUrl("/failer.jsp")
                .and()
                //指定登出
                .logout()
                //指定登出的路径
                .logoutSuccessUrl("/logout")
                //指定登出之后清除session
                .invalidateHttpSession(true)
                //指定登录之后跳转到登录页面
                .logoutSuccessUrl("/login.jsp")
                .and()
                //配置csrf跨站请求伪造是关闭的,所以存在跨站请求伪造的危险
                .csrf()
                .disable();
    }
}

3.9 测试

注意还是用插件启动项目,使用数据库表中的用户名和密码,可以使用xiaoming/123456进行登录,之前给的脚本中,密码是经过加密处理的。

4、整合实现授权功能

授权操作就比较简单了,只需要开启授权注解,然后在对应的处理器方法上面添加相关的注解即可

4.1 启动类上添加开启方法级的授权注解

package com.zdwhong;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;

/**
 * @author ZDW
 * @create 2020-07-18 21:24
 */
@SpringBootApplication
@MapperScan("com.zdwhong.mapper")
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true, jsr250Enabled = true)
public class SecurityJspApplication {
    public static void main(String[] args) {
        SpringApplication.run(SecurityJspApplication.class,args);
    }
}

securedEnabled = true,prePostEnabled = true, jsr250Enabled = true :者三个值分别对应我们之前说到的Spring Security自己的注解,Spring的注解和jsr250的注解开启

4.2 在产品处理器类上添加注解

要求产品列表功能必须具有ROLE_PRODUCT角色才能访问,上面给的脚本中,xiaoming是有这个角色的,但是xiaoma没有这个角色

package com.zdwhong.controller;

import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author ZDW
 * @create 2020-07-18 21:30
 */
@Controller
@RequestMapping("product")
public class ProductController {

    @Secured("ROLE_PRODUCT")
    @RequestMapping("/findAll")
    //@ResponseBody  //返回json数据,不进行视图解析器
    public String findAll() {
        //return "success";

        //经过视图解析器,跳转到product-list.jsp页面
        return "product-list";
    }
}

4.3 测试

使用xiaoming/123456登录,可以正常访问页面:http://127.0.0.1:8080/product/findAll

如果是xiaoma/123456登录,则是403错误:

在这里插入图片描述

4.4 定义全局异常处理

上面的403错误显示不友好,我们可以编写全局的异常处理,拦截到403异常,然后跳转到403页面:

package com.zdwhong.exception;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * @author ZDW
 * @create 2020-07-19 16:20
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public String exceptionHandler(Exception e)) {
        if((e instanceof AccessDeniedException) {//403会抛出的异常
            //如果是权限不足异常,则跳转到权限不足页面!
            return "redirect:/403.jsp";
        }
        //其余的异常都跳转到500页面
        return "redirect:/500.jsp";
    }
}

重启就可以看到效果了。

😕/127.0.0.1:8080/product/findAll

如果是xiaoma/123456登录,则是403错误:

[外链图片转存中…(img-PI1rsqPW-1599807230329)]

4.4 定义全局异常处理

上面的403错误显示不友好,我们可以编写全局的异常处理,拦截到403异常,然后跳转到403页面:

package com.zdwhong.exception;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * @author ZDW
 * @create 2020-07-19 16:20
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public String exceptionHandler(Exception e)) {
        if((e instanceof AccessDeniedException) {//403会抛出的异常
            //如果是权限不足异常,则跳转到权限不足页面!
            return "redirect:/403.jsp";
        }
        //其余的异常都跳转到500页面
        return "redirect:/500.jsp";
    }
}

重启就可以看到效果了。

本次就到此为止了,下次是SpringBoot的分布式整合

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值