使用 Spring Security 时经常会看见 403(无权限),默认情况下 显示的效果如下:
而在实际项目中可能都是一个异步请求,显示上述效果对于用户 就不是特别友好了。
Spring Security 支持自定义权限受限。
具体做法
1.新建一个类实现AccessDeniedHandler重写handle方法
2 配置类添加异常
package com.lin.springsecurity.handler;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* 自定义403错误
* @Author
* @Date 2020/8/19 20:24
*/
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
//1 设置响应状态码 >这里设置403
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setContentType("application/json:charset=utf-8");
PrintWriter writer = response.getWriter();
writer.println("{"code":"403","msg":"无权限"}");
writer.flush();
writer.close();
}
}
package com.lin.springsecurity.config;
import com.lin.springsecurity.handler.MyAccessDeniedHandler;
import com.lin.springsecurity.handler.MyAuthenticationFailureHandler;
import com.lin.springsecurity.handler.MyAuthenticationSuccessHandler;
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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @Author ccgg
* @Date 2020/8/18 22:56
* 创建 PasswordEncoder 实例,在spring启动时,注入容器中
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyAccessDeniedHandler myAccessDeniedHandler;
/**
* 创建加密对象
* @return
*/
@Bean
public PasswordEncoder getPE(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//表单认证
http.formLogin()
//当发现login时认为是登录需要执行我们自定义的登录逻辑 >里面的url是登录页面表单的提交地址
.loginProcessingUrl("/login")
//登录成功后请求地址 请求方法必须是post的 这里是跳转控制器
// .successForwardUrl("/toMain")
.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
//登录失败后请求访问的地址 >这里访问的是控制器
//.failureForwardUrl("/failLogin")
.failureHandler(new MyAuthenticationFailureHandler("/fail.html"))
//设置登录页面
.loginPage("/login.html")
.usernameParameter("uuname")
.passwordParameter("ppword")
;
//url拦截认证 >所有请求都必须被认证 必须登录后才可以访问
http.authorizeRequests()
//设置不需要拦截的页面
.antMatchers("/login.html").permitAll()
.antMatchers("/fail.html").permitAll()
//放行所有静态资源
.antMatchers("/js/**","/css/**","/images/**").permitAll()
//放行任意文件夹中以png结尾的图片
.antMatchers("/**/*.png").permitAll()
//所有请求都必须被认真,必须登录后才能访问
.anyRequest().authenticated();
//关闭csrf防护 >只有关闭了,来自表单的请求
http.csrf().disable();
//异常处理
http.exceptionHandling()
.accessDeniedHandler(myAccessDeniedHandler);
}
}