基于session
1.导入依赖
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.49</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.自定义的用户登录认证逻辑
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.Set;
/**
* 自定义的用户登录认证逻辑
*/
@Component
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Set authoritiesSet = new HashSet();
// 模拟从数据库中获取用户的角色及权限
GrantedAuthority authority = new SimpleGrantedAuthority("/v3");
authoritiesSet.add(authority);
String encode = passwordEncoder.encode("123456");
// 模拟对比用户密码
// 登录成功
return new User( username, encode, authoritiesSet);
}
}
3.自定义access权限控制
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
/**
* 自定义access权限控制
*/
@Component("rbacauthorityservice")
public class RbacAuthorityService {
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
Object userInfo = authentication.getPrincipal();
if (userInfo instanceof UserDetails) {
UserDetails userDetails = (UserDetails) userInfo;
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
String requestURI = request.getRequestURI();
// 模拟放行无需权限的接口
if("/v1".equals(request.getRequestURI())){
return true;
}
// 验证用户是否有包含该权限
return authorities.contains(new SimpleGrantedAuthority(requestURI));
}
return false;
}
}
4.自定义的安全校验
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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;
@EnableWebSecurity
@Configuration
public class MyWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
AjaxAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
AjaxAccessDeniedHandler accessDeniedHandler;
/**
* 设置默认的加密方式(强hash方式加密)
*/
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 去掉 CSRF
http.csrf().disable()
.authorizeRequests()//定义哪些URL需要被保护、哪些不需要被保护
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // OPTIONS放行
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers(HttpMethod.GET, "/logout").permitAll()
.anyRequest()
.access("@rbacauthorityservice.hasPermission(request,authentication)"); // RBAC 动态 url 认证
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 无权访问 JSON 格式的数据
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);//匿名用户访问无权限资源时的异常处理
}
}
import java.io.Serializable;
/**
* @author zhoumin
* @version 1.0
* @description API层统一参数回调
* @date 2021/6/17 15:17
*/
public class ApiResult<T> implements Serializable {
private static final long serialVersionUID = -4038477637423906177L;
/**
* 响应体
*/
private T data;
/**
* 是否成功
*/
private boolean isSuccess;
/**
* 请求返回的消息
*/
private String msg;
/**
* 错误码
*/
private String errorCode;
/**
* 请求成功回调
*/
public static ApiResult successMsg() {
return new ApiResult()
.setErrorCode("200")
.setSuccess(true)
.setMsg("ok");
}
/**
* 请求成功回调
*
* @param Object 对象
*/
public static ApiResult successMsg(Object Object) {
return new ApiResult()
.setErrorCode("200")
.setSuccess(true)
.setMsg("ok")
.setData(Object);
}
/**
* 请求失败回调
*
* @param code 状态码
* @param msg 描述信息
*/
public static ApiResult errorMsg(String code, String msg) {
return new ApiResult()
.setErrorCode(code)
.setMsg(msg)
.setSuccess(false);
}
/**
* 请求失败回调
*
* @param msg 描述信息
*/
public static ApiResult errorMsg(String msg) {
return new ApiResult()
.setErrorCode("500")
.setMsg(msg)
.setSuccess(false);
}
/**
* 请求失败回调
* @param errorCode 错误枚举
*/
public static ApiResult errorMsg(ErrorCode errorCode) {
return new ApiResult()
.setErrorCode(errorCode.getErrorCode())
.setMsg(errorCode.getErrorMsg())
.setSuccess(false);
}
public T getData() {
return data;
}
public String getErrorCode() {
return errorCode;
}
public String getMsg() {
return msg;
}
public ApiResult<T> setData(T data) {
this.data = data;
return this;
}
public boolean isSuccess() {
return isSuccess;
}
public ApiResult<T> setSuccess(boolean success) {
isSuccess = success;
return this;
}
public ApiResult<T> setErrorCode(String errorCode) {
this.errorCode = errorCode;
return this;
}
public ApiResult<T> setMsg(String msg) {
this.msg = msg;
return this;
}
}
import com.alibaba.fastjson.JSON;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author zhoumin
* @version 1.0
* @description 用户权限不足时反给前端的数据
* @date 2021/6/21 10:32
*/
@Component
public class AjaxAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException {
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setHeader("Content-Type", "application/json");
httpServletResponse.getWriter().write(JSON.toJSONString(ApiResult.errorMsg("用户权限不足")));
}
}
import com.alibaba.fastjson.JSON;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author zhoumin
* @version 1.0
* @description 用户没登陆时反给前端的数据
* @date 2021/6/21 10:33
*/
@Component
public class AjaxAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setHeader("Content-Type", "application/json");
httpServletResponse.getWriter().write(JSON.toJSONString(ApiResult.errorMsg("用户未登录")));
}
}
5.测试类
import com.zm.config.MyUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@Autowired
MyUserDetailsService myUserDetailsService;
@GetMapping("v1")
public String v1() {
return "v1 hello world";
}
@GetMapping("v2")
public String v2() {
return "v2 hello world";
}
@GetMapping("v3")
public String v3() {
return "v3 hello world";
}
@PostMapping("/login")
public String login() {
UserDetails userDetails = myUserDetailsService.loadUserByUsername("zhou");
SecurityContextHolder.getContext()
.setAuthentication(
new UsernamePasswordAuthenticationToken(userDetails,
userDetails.getPassword(), userDetails.getAuthorities()));
return "login ok";
}
@GetMapping("/logout")
public void logout() {
SecurityContextHolder.clearContext();
}
}
6.测试结果
未登录进行提示
登录成功后可以进行访问
基于spring session集群 分布式中的使用
链接: springboot-整合spring-session-redis在nginx下实现session共享(九).
补充链接: Springboot http session支持分布式;同时支持 cookie 和 header 传递;websocket 连接 共享 http session.
/**
* 分布式session-redis配置
*/
// session托管到redis
// maxInactiveIntervalInSeconds单位:秒;
// RedisFlushMode有两个参数:ON_SAVE(表示在response commit前刷新缓存),IMMEDIATE(表示只要有更新,就刷新缓存)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.ConfigureRedisAction;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
@EnableRedisHttpSession(redisNamespace = "session")
@Configuration
public class RedisHttpSessionConfig {
//这里有个小坑,如果服务器用的是云服务器,不加这个会报错
@Bean
public static ConfigureRedisAction configureRedisAction() {
return ConfigureRedisAction.NO_OP;
}
//可自定义session策略,这里配置的是Header方式(有提供Header,Cookie等方式)
@Bean
public HeaderHttpSessionIdResolver httpSessionStrategy() {
// 设置HttpServletRequest中Header里的自定义token名称
return new HeaderHttpSessionIdResolver("token");
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@EnableWebSecurity
@Configuration
public class MyWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
AjaxAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
AjaxAccessDeniedHandler accessDeniedHandler;
/**
* 设置默认的加密方式(强hash方式加密)
*/
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 去掉 CSRF
http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and().authorizeRequests()//定义哪些URL需要被保护、哪些不需要被保护
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // OPTIONS放行
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers(HttpMethod.GET, "/logout").permitAll()
.antMatchers(HttpMethod.GET, "/get/**").permitAll()// /get/xxx放行
.anyRequest()
.access("@rbacauthorityservice.hasPermission(request,authentication)"); // RBAC 动态 url 认证
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 无权访问 JSON 格式的数据
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);//匿名用户访问无权限资源时的异常处理
}
}
基于JWT
分布式项目中的使用
springboot和springsecurity整合OAuth2
Spring Cloud Security OAuth2 实现分布式系统授权
链接: 深入理解Spring Cloud Security OAuth2及JWT.
解决与springboot admin的安全认证
解决方案:配置多个WebSecurityConfigurerAdapter
按Order() 顺序加载
链接: 整合springboot admin 监控 – springboot(十五).
链接: 多个 WebSecurityConfigurerAdapter 的 order 问题.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
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.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Order(3)
@EnableWebSecurity
@Configuration
public class MyWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
AjaxAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
AjaxAccessDeniedHandler accessDeniedHandler;
/**
* 设置默认的加密方式(强hash方式加密)
*/
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 去掉 CSRF
http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
.and().authorizeRequests()//定义哪些URL需要被保护、哪些不需要被保护
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // OPTIONS放行
.antMatchers("/actuator/**").permitAll() // actuator监控接口放行,不指定请求方式
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers(HttpMethod.GET, "/logout").permitAll()
.antMatchers(HttpMethod.GET, "/get/**").permitAll()
.anyRequest()
.access("@rbacauthorityservice.hasPermission(request,authentication)"); // RBAC 动态 url 认证
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 无权访问 JSON 格式的数据
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);//匿名用户访问无权限资源时的异常处理
}
}
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
@Order(4)
@Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
/***
* 指定让它拦截actuator的接口即可,业务相关的接口由业务权限系统去控制
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests().antMatchers("/actuator/**").authenticated().anyRequest().permitAll();
// 关闭CSRF,否则POST请求必须带上token
http.csrf().disable();
}
/**
* 在内存中配置一个用户,admin/admin分别是用户名和密码,这个用户拥有USER角色。
* withDefaultPasswordEncoder 被遗弃,原因是不安全,只能在例子中使用
*
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
auth.inMemoryAuthentication()
.withUser("user")
.password(encoder.encode("user"))
.roles("USER");
}
}
参考链接
链接: spring-session(一)揭秘.
链接: Springboot + Spring Security 实现前后端分离登录认证及权限控制.
链接: springboot+springsecurity+mybatis+JWT+Redis 实现前后端离(实战篇).
链接: SpringBoot Security前后端分离登录验证.
链接: SpringBoot+SpringSecurity+jwt实现前后端分离的权限认证(不用security的登陆和注销).
链接: 基于 spring-session 解决分布式 session 共享问题.
User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities)
其中参数:
String username:用户名
String password: 密码
boolean enabled: 账号是否可用
boolean accountNonExpired:账号是否过期
boolean credentialsNonExpired:密码是否过期
boolean accountNonLocked:账号是否锁定
Collection<? extends GrantedAuthority> authorities):用户权限列表
基于固定角色的权限认证
package com.example.course.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@EnableWebSecurity
@Configuration
public class MyWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
AjaxAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
AjaxAccessDeniedHandler accessDeniedHandler;
/**
* 设置默认的加密方式(强hash方式加密)
*/
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 去掉 CSRF
http.csrf().disable()
.authorizeRequests()// 开启权限控制,通过ANT规范,自定义逻辑
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // OPTIONS放行
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers(HttpMethod.GET, "/logout").permitAll()
// 可以用请求url前准 基于角色的权限控制
// .antMatchers("/admin/**").hasRole("GLY")
// .antMatchers("/xs/**").hasRole("XS")
.anyRequest()//任意请求
.authenticated();//必须经过认证 只要登陆就能访问
;
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 无权访问 JSON 格式的数据
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);//匿名用户访问无权限资源时的异常处理
}
}
package com.example.course.test;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.HashSet;
import java.util.Set;
/**
* @Author:lzf
* @Date: 2022/1/25
*/
@Component
public class MyUserDetailsService implements UserDetailsService {
@Resource
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Set authoritiesSet = new HashSet();
// 模拟从数据库中获取用户的角色及权限
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_XS");
authoritiesSet.add(authority);
String encode = passwordEncoder.encode("123456");
// 模拟对比用户密码
// 登录成功
return new User( username, encode, authoritiesSet);
}
}
package com.example.course.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author:lzf
* @Date: 2022/1/25
*/
@RestController
public class TestController {
@Autowired
MyUserDetailsService myUserDetailsService;
@PreAuthorize("hasRole('ROLE_XS')")
@GetMapping("/xs/v1")
public String v1() {
return "v1 hello world";
}
@PreAuthorize("hasRole('ROLE_LS')")
@GetMapping("v2")
public String v2() {
return "v2 hello world";
}
@PreAuthorize("hasRole('ROLE_GLY')")
@GetMapping("/admin/v3")
public String v3() {
return "v3 hello world";
}
@PostMapping("/login")
public String login() {
UserDetails userDetails = myUserDetailsService.loadUserByUsername("zhou");
SecurityContextHolder.getContext()
.setAuthentication(
new UsernamePasswordAuthenticationToken(userDetails,
userDetails.getPassword(), userDetails.getAuthorities()));
return "login ok";
}
@GetMapping("/logout")
public void logout() {
SecurityContextHolder.clearContext();
}
}
注意
在UserDetailsService使用loadUserByUsername构建当前登录用户时,可以选择两种授权方法,即角色授权和权限授权,对应使用的代码是hasRole和hasAuthority,而这两种方式在设置时也有不同,下面介绍一下:
角色授权:授权代码需要加ROLE_前缀,controller上使用时不要加前缀
权限授权:设置和使用时,名称保持一至即可
security 鉴权方式常用的有两种配置,
1、配置文件中配置;
2、使用注解标注;
他们都是基于 acess 表达式,如果需要自定义逻辑的鉴权认证,只需要自定义 access 表达式即可。
注解默认不可用,通过开启注解:在配置类中开启注解
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Secured:专门判断用户是否具有角色,可以写在方法或类上,参数以 ROLE_ 开头
@PreAuthorize\PostAuthorize: PreAuthorize 访问的类或方法执行前判断权限,而 PostAuthorize 在执行之后,Post 基本不用;允许与 ROLE_ 开头。
@Component
public class MyUserDetailService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
User user = new User(name,
passwordEncoder.encode("123456"),
AuthorityUtils.commaSeparatedStringToAuthorityList("read,ROLE_USER"));//设置权限和角色
// 1. commaSeparatedStringToAuthorityList放入角色时需要加前缀ROLE_,而在controller使用时不需要加ROLE_前缀
// 2. 放入的是权限时,不能加ROLE_前缀,hasAuthority与放入的权限名称对应即可
return user;
}
}
//读权限
@GetMapping("/read")
@PreAuthorize("hasAuthority('read')")
public String readDate() {
return "have a read authority";
}
//读写权限
@GetMapping("/read-or-write")
@PreAuthorize("hasAnyAuthority('read','write')")
public String readWriteDate() {
return "have a read or write authority";
}
//admin角色
@GetMapping("/admin-role")
@PreAuthorize("hasRole('admin')")
public String readAdmin() {
return "have a admin role";
}
链接: SpringSecurity设置角色和权限.
链接: springboot security 权限控制 – @PreAuthorize 的使用.
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/133933.html