授权(权限)
常用方法 - 以下方法都需要组合起来才能使用。
(1)anyRequest()
任何请求,注意需要把它放到最后边
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 自定义登录页面
http.formLogin()
.loginPage("/login.html");
// 在这里写授权逻辑
// 除了login api接口,其他api接口都需要拦截,做授权
http.authorizeRequests()
.antMatchers("/login").permitAll()
// 任何请求都需要授权,注意顺序 从上至下
.anyRequest().authenticated();
// 关闭csrf防护
http.csrf().disable();
}
@Bean
public PasswordEncoder bCryptPasswordEncoder () {
return new BCryptPasswordEncoder();
}
}
(2)authenticated()
所有请求必须认证才能访问,但是,一写静态资源:如:css、js,不需要授权,此时就需要antMatchers() 了。
(3)antMatchers()
需要放行的api、静态资源、目录等。
参数一:可以放行指定的请求方法(只写一个参数的话,代表任何的请求方法都可以)。
参数二:api接口,或一个.html页面。
参数一是必定向参数,每个参数是一个ant表达式,用于匹配URL规则。
规则如下:
? 匹配一个字符
* 匹配0个或多个字符
** 匹配0个或多个目录
在实际项目中,经常需要放行所有的静态资源,如下:
antMatchers("/js/**", "/css/**").permitAll();
还有一种放行方式,如下:只要是.js文件都放行
antMatchers("/**/*.js").permitAll();
只要是图片jpg或png就放行
antMatchers("/**/*.jpg", "/**/*.png").permitAll()
如:
(1) 只放行static和public目录下的所有文件。
http.authorizeRequests()
// /login接口不需要授权
.antMatchers("/static/**").permitAll()
.antMatchers("/public/**").permitAll()
// 任何请求都需要授权
.anyRequest().authenticated();
(2)放行login.html 、error.html、static目录下的css目录及js目录:
// 请求授权
http.authorizeRequests()
// 匹配一个可以放行的路径
.mvcMatchers("/login.html", "/error.html", "/css/**", "/js/**")
.permitAll()
.anyRequest().authenticated(); // 任何请求都需要授权
(4).regexMatchers()
正则匹配。
参数一:可以放行指定的请求方法(只写一个参数的话,代表任何的请求方法都可以)。。
参数二:api接口,或一个正则表达式。
例:只放行get请求方法的 /demo 接口
.regexMatchers(HttpMethod.GET, "/demo").permitAll()
(5)mvcMatchers()
MVC匹配。
只要是 /test/demo的api就放行,下边的servletPath() 与下边配置文件中的servlet.path 对应,如果加上此配置,访问所有的api都需要加上前缀 /test
.mvcMatchers("/demo").servletPath("/test").permitAll()
这个 mvcMatchers("/demo").servletPath("/test") 相当于 antMatchers("/demo/test")
servletPath这个方法只在mvcMatchers()方法中才有。
(6)基于权限来控制访问 - hasAuthority("权限")
1、
.mvcMatchers("/main.html").hasAuthority("superAdmin") 注意权限大小写敏感!!!
用户登录之后,假设某些页面需要拥有某个权限才能访问:
登陆成功,进入登陆成功页面,如果想进入主页面,需要superAdmin这个权限才能访问,
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 表单的登录
// ··· ···
// 请求授权
http.authorizeRequests()
// 匹配一组可以放行的路径
.mvcMatchers("/login.html", "/error.html", "/css/**", "/js/**", "/**/*.jpg")
.permitAll()
// 这个main.html需要superAdmin权限才能访问
.mvcMatchers("/main.html")
.hasAuthority("superAdmin")
.anyRequest().authenticated(); // 任何请求都需要授权
}
}
点击,403禁止访问,也就是没有这个权限,这个权限我们在下边可以配置:
当给这个用户加上superAdmin后,在访问时,就可以进入main.html页面了
2、多个权限 - hasAnyAuthority( "权限1", "权限2", ··· ··· )
如果访问某个页面对应多个权限,也就是有其中一个权限就能访问该页面,用如下方法
(7)基于角色来控制访问 - hasRole("角色")
如何添加角色呢?
也很简单,也是在添加权限这里加,与权限区别在于:角色前边必须添加 ROLE_
使用:
.mvcMatchers("/main.html").hasRole("lxc") // 添加lxc角色,也可以使用 hasAnyRole("角色", ··· ···)添加多个角色
(8)基于ip地址去控制访问 - hasIpAddress("ip地址")
在实际开发中,有事会有这样的需求:只有这一台服务器才能访问某个api地址,那么我们可以用基于ip地址去控制访问(只有这个ip地址才能登陆,如果不是这个ip地址就不允许登陆)。
此时用localhost访问main.html直接禁止访问了
改用127.0.0.1试下,成功:
(9)自定义403页面
之前如果访问没有权限的页面会出现403页面,自定义的话,如下:
1、首先 实现 AccessDeniedHandler接口,重写方法
package com.lxc.sequrity.config;
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;
@Component
public class PageForbidenHandler implements AccessDeniedHandler {
@Override
public void handle(
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setHeader("Content-Type", "application/json;charset=utf-8");
httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
PrintWriter writer = httpServletResponse.getWriter();
writer.write("{\"msg\": 权限不足,不能访问}");
writer.flush();
writer.close();
}
}
2、在配置类中,注入,配置:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
PageForbidenHandler pageForbidenHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
// ··· ···
// 403异常处理
http.exceptionHandling()
.accessDeniedHandler(pageForbidenHandler);
}
}
(10) access()方法
上边所有放行的方法,内部都是基于access()方法调用的,比如 :
.mvcMatchers().permitAll()、.mvcMatchers().hasAuthority()、··· ···
所有的放行方法,都可以用access()方法来实现,效果完成一样的: