技术选型
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的分布式整合