目录
1.先在数据库创建用户表t_user和客户端配置表oauth_client_details
4.更改resources配置文件名称为application.yml,增加配置参数
5.在study下面新建各种包名,在resources下面新建mapper文件夹,编写相应的代码
6.在SpringBootStudyApplication添加注解@MapperScan扫描Mapper
7.打开类SpringBootStudyApplication,右键运行
1.先在数据库创建用户表t_user和客户端配置表oauth_client_details
CREATE TABLE `t_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键id',
`username` varchar(255) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码',
`rolename` varchar(255) DEFAULT NULL COMMENT '角色,逗号隔开',
`enabled` int(11) DEFAULT NULL COMMENT '是否启用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `oauth_client_details` (`client_id` varchar(128) NOT NULL COMMENT '客户端ID',
`resource_ids` varchar(256) DEFAULT NULL COMMENT '资源ID集合,多个用逗号分隔',
`client_secret` varchar(256) DEFAULT NULL COMMENT '客户端密钥',
`scope` varchar(256) DEFAULT NULL COMMENT '权限范围',
`authorized_grant_types` varchar(256) DEFAULT NULL COMMENT '授权类型',
`web_server_redirect_uri` varchar(256) DEFAULT NULL COMMENT '重定向URI',
`authorities` varchar(256) DEFAULT NULL COMMENT '权限',
`access_token_validity` int(11) DEFAULT NULL COMMENT '访问令牌有效期(秒)',
`refresh_token_validity` int(11) DEFAULT NULL COMMENT '刷新令牌有效期(秒)',
`additional_information` varchar(4096) DEFAULT NULL COMMENT '附加信息',
`autoapprove` varchar(256) DEFAULT NULL COMMENT '是否自动授权',
PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.插入表测试数据
#第一条密码是123456,第二条是666666
INSERT INTO `springboot_study`.`t_user` (`id`, `username`, `password`, `rolename`, `enabled`) VALUES (1, 'saas', '2a10$prTTUfRO8cBfpZKxjbJ6XO2oJ5ILCeocEgtYomhK9BU8ELTFk90Da', 'ROLE_USER', 1);
INSERT INTO `springboot_study`.`t_user` (`id`, `username`, `password`, `rolename`, `enabled`) VALUES (2, 'admin', '2a10$b5c2KKDQSo.u8MEDDrSbh.Z0ZsbVU1.2ZNapGRgTvLw0fLMeqFIA.', 'ROLE_ADMIN', 1);
INSERT INTO oauth_client_details (
client_id,
resource_ids,
client_secret,
scope,
authorized_grant_types,
web_server_redirect_uri,
authorities,
access_token_validity,
refresh_token_validity,
additional_information,
autoapprove
) VALUES (
'client1', -- 客户端ID
'oauth2-resource', -- 资源ID(需与资源服务器配置的resourceId一致)
'2a10$LQx7R87M8J2l3Y8X9Z0A5eOeFgHhIjKlMnOpQrStUvWxYz1234567', -- 客户端密钥(BCrypt加密,原文:secret123)
'read,write', -- 权限范围
'password,refresh_token,client_credentials', -- 支持的授权类型(密码模式、刷新令牌、客户端凭证模式)
null, -- 重定向URI(授权码模式需配置)
null, -- 客户端权限
3600, -- 访问令牌有效期(秒)
86400, -- 刷新令牌有效期(秒)
'{}', -- 附加信息
'true' -- 是否自动授权
);
3.打开pom.xml添加依赖
java
<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>
<!--mysql数据库驱动程序-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!--支持通过jdbc连接数据库-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- MyBatis-Plus 核心(与 2.7.4 兼容) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!--mybatis-plus代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.1</version>
</dependency>
<!--mybatis-plus代码生成器依赖的模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<!-- Lombok(简化实体类) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--安全框架spring security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--OAuth2授权服务器 -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.6.8</version>
</dependency>
<!--jwt支持-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.1.RELEASE</version>
</dependency>
<!--jwt 核心库-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
4.更改resources配置文件名称为application.yml,增加配置参数

java
server:
port: 8888 #指定启动的端口
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver #数据库驱动
url: jdbc:mysql://localhost:3306/springboot_study?serverTimezone=Asia/Shanghai&characterEncoding=utf-8&useSSL=false #数据库的url
username: root #数据库的用户名
password: 123456 #数据库的密码
type: com.alibaba.druid.pool.DruidDataSource #指定数据源
druid:
initial-size: 5 # 初始化大小
min-idle: 10 # 最小连接数
max-active: 20 # 最大连接数
max-wait: 60000 # 获取连接时的最大等待时间
min-evictable-idle-time-millis: 300000 # 一个连接在池中最小生存的时间,单位是毫秒
time-between-eviction-runs-millis: 60000 # 多久才进行一次检测需要关闭的空闲连接,单位是毫秒
filters: stat,wall # 配置扩展插件:stat-监控统计,log4j-日志,wall-防火墙(防止SQL注入),去掉后,监控界面的sql无法统计
validation-query: SELECT 1 # 检测连接是否有效的 SQL语句,为空时以下三个配置均无效
test-on-borrow: true # 申请连接时执行validationQuery检测连接是否有效,默认true,开启后会降低性能
test-on-return: true # 归还连接时执行validationQuery检测连接是否有效,默认false,开启后会降低性能
test-while-idle: true # 申请连接时如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效,默认false,建议开启,不影响性能
stat-view-servlet:
enabled: true # 是否开启 StatViewServlet
allow: 127.0.0.1 # 访问监控页面的白名单,默认127.0.0.1(多个以逗号隔开)
deny: 192.168.0.1 # 访问监控页面的黑名单(存在共同时,deny优先于allow)
login-username: admin # 访问监控页面的登陆账号
login-password: 123456 # 访问监控页面的登陆密码
filter:
stat:
enabled: true # 是否开启 FilterStat,默认true
log-slow-sql: true # 是否开启 慢SQL 记录,默认false
slow-sql-millis: 5000 # 慢 SQL 的标准,默认 3000,单位:毫秒
merge-sql: false # 合并多个连接池的监控数据,默认false
# jwt配置
jwt:
key: mySecretKey123 # jwt签名密钥(生产环境需使用复杂密钥)
access-token-expire: 3600 # 访问令牌有效期(秒)
refresh-token-expire: 86400 # 刷新令牌有效期(秒)
oauth:
client-id: client1 # 与数据库中oauth_client_details的client_id一致
5.在study下面新建各种包名,在resources下面新建mapper文件夹,编写相应的代码

entity层
java
package com.saas.study.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.Setter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
/**
* <p>
*
* </p>
*
* @author yy
* @since 2025-11-17
*/
@Getter
@Setter
@TableName("t_user")
public class User implements UserDetails {
/**
* 主键id
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 是否启用
*/
private Boolean enabled;
/**
* 角色集合 ROLE_ADMIN、ROLE_USER
*/
private List<String> roles;
/**
* 角色字段(逗号隔开)
*/
private String roleName;
// 核心方法:返回用户的权限(Spring Security 要求角色以 ROLE_ 开头)
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<String> roleList= Arrays.stream(roleName.split(","))
.collect(Collectors.toList());
return roleList.stream()
.map(role -> new SimpleGrantedAuthority(role))
.collect(Collectors.toList());
}
// 账户是否未过期(默认 true)
@Override
public boolean isAccountNonExpired() {
return true;
}
// 账户是否未锁定(默认 true)
@Override
public boolean isAccountNonLocked() {
return true;
}
// 凭证是否未过期(默认 true)
@Override
public boolean isCredentialsNonExpired() {
return true;
}
// 账户是否启用(关联数据库 enabled 字段)
@Override
public boolean isEnabled() {
return enabled;
}
}
controller层
java
package com.saas.study.controller;
import com.saas.study.entity.User;
import com.saas.study.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.web.bind.annotation.*;
import org.springframework.stereotype.Controller;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 前端控制器
* </p>
*
* @author yy
* @since 2025-11-17
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService;
@Autowired
private AuthenticationManager authenticationManager; //认证管理器
@Autowired
private ClientDetailsService clientDetailsService; //客户端信息服务
@Autowired
private AuthorizationServerTokenServices tokenServices; //令牌服务
@Value("${oauth.client-id:client1}") //配置文件中配置客户端ID
private String clientId;
//登录接口
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password,
@RequestParam(required = false) String code) {
String result = null;
try {
//手动触发用户名密码认证(会调用 UserDetailsService 校验用户)
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(authToken);
//构建客户端信息(模拟客户端认证)
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
Map<String, String> requestParameters = new HashMap<>();
OAuth2Request oAuth2Request = new OAuth2Request(
requestParameters, clientId, clientDetails.getAuthorities(),
true, clientDetails.getScope(), clientDetails.getResourceIds(),
null, null, null
);
//构建 OAuth2 认证对象(用户认证 + 客户端认证)
OAuth2Authentication oAuth2Authentication =
new OAuth2Authentication(oAuth2Request, authentication);
//生成令牌(调用授权服务器的令牌服务)
OAuth2AccessToken accessToken = tokenServices.createAccessToken(oAuth2Authentication);
//返回结果(这里手动拼接,自行更改)
StringBuilder resultBuilder = new StringBuilder();
resultBuilder.append("{")
.append("\"code\":200,")
.append("\"message\":\"登录成功\",")
.append("\"data\":{")
.append("\"access_token\":\"").append(accessToken.getValue()).append("\",")
.append("\"token_type\":\"").append(accessToken.getTokenType()).append("\",")
.append("\"expires_in\":").append(accessToken.getExpiresIn()).append(",")
.append("\"scope\":[\"").append(String.join("\",\"", accessToken.getScope())).append("\"]");
//可选:添加刷新令牌
if (accessToken.getRefreshToken() != null) {
resultBuilder.append(",\"refresh_token\":\"").append(accessToken.getRefreshToken().getValue()).append("\"");
}
resultBuilder.append("}}");
result = resultBuilder.toString();
} catch (Exception e) {
//认证失败
result = "{\"code\":500,\"message\":"+e.getMessage()+"}";
}
return result;
}
//获取所有的用户信息
@GetMapping("/base/getUserInfoList")
public List<User> getUserInfoList(){
return userService.getUserInfoList();
}
//调整登录接口
@GetMapping("/tologin")
public String userInfo() {
return "去登录";
}
}
service层
java
package com.saas.study.service;
import com.saas.study.entity.User;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* <p>
* 服务类
* </p>
*
* @author yy
* @since 2025-11-17
*/
public interface UserService extends IService<User> {
List<User> getUserInfoList();
}
java
package com.saas.study.service.impl;
import com.saas.study.entity.User;
import com.saas.study.mapper.UserMapper;
import com.saas.study.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
/**
* <p>
* 服务实现类
* </p>
*
* @author yy
* @since 2025-11-17
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Resource
private UserMapper userMapper;
@Override
public List<User> getUserInfoList() {
return userMapper.getUserInfoList();
}
}
java
package com.saas.study.service.impl;
import com.saas.study.entity.User;
import com.saas.study.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
// Spring Security 会自动调用此方法,根据用户名查询用户信息
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//查询用户
User user = userMapper.selectUserByUsername(username);
if (user == null || StringUtils.isBlank(user.getRoleName())) {
throw new UsernameNotFoundException("用户名不存在");
}
//设置角色
List<String> roles = Arrays.stream(user.getRoleName().split(","))
.collect(Collectors.toList());
user.setRoles(roles);
return user;
}
}
mapper层
java
package com.saas.study.mapper;
import com.saas.study.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
/**
* <p>
* Mapper 接口
* </p>
*
* @author yy
* @since 2025-11-17
*/
public interface UserMapper extends BaseMapper<User> {
List<User> getUserInfoList();
User selectUserByUsername(String username);
}
java
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.saas.study.mapper.UserMapper">
<select id="getUserInfoList" resultType="com.saas.study.entity.User">
select id,username,password,rolename from t_user
</select>
<select id="selectUserByUsername" resultType="com.saas.study.entity.User">
SELECT id, username, password, enabled,rolename
FROM t_user
WHERE username = #{username}
</select>
</mapper>
component层
java
package com.saas.study.component;
import org.springframework.http.HttpStatus;
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;
import java.io.PrintWriter;
/**
* 自定义权限不足处理器(403)
*/
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException {
// 前后端分离:返回JSON
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpStatus.FORBIDDEN.value()); // 403状态码
PrintWriter out = response.getWriter();
// 自定义JSON响应
out.write("{\"code\":403,\"message\":\"权限不足,无法访问该资源\",\"detail\":\"" + accessDeniedException.getMessage() + "\"}");
out.flush();
out.close();
}
}
java
package com.saas.study.component;
import org.springframework.http.HttpStatus;
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;
import java.io.PrintWriter;
/**
* 自定义认证失败处理器(401):处理令牌无效、过期、未携带令牌等场景
*/
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException {
//前后端分离:返回JSON
response.setContentType("application/json;charset=utf-8");
response.setStatus(HttpStatus.UNAUTHORIZED.value()); // 401状态码
PrintWriter out = response.getWriter();
//自定义JSON响应
String message;
String detail = authException.getMessage();
// 区分异常场景,返回更精准的提示
if ("Full authentication is required to access this resource".equals(detail)) {
message = "请先登录"; // 未登录场景
} else if (detail.contains("expired")) {
message = "登录已过期,请重新登录"; // 令牌过期
} else if (detail.contains("invalid")) {
message = "令牌无效"; // 令牌错误
} else {
message = "认证失败,无法访问资源"; // 其他认证异常
}
// 拼接JSON响应
out.write("{\"code\":401,\"message\":\"" + message + "\",\"detail\":\"" + detail + "\"}");out.flush();
out.close();
}
}
config层
java
package com.saas.study.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import javax.sql.DataSource;
/**
* 认证服务配置类
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DataSource dataSource;
@Value("${jwt.key}")
private String secretKey;
@Value("${jwt.access-token-expire}")
private int accessTokenExpire;
//配置客户端信息来源(数据库)
@Bean
public JdbcClientDetailsService customClientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
//配置jwt令牌转换器
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
//根据需要自定义jwt生成和解析
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(secretKey);
return converter;
}
//配置令牌存储(jwt)
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
//配置令牌服务(关键:关联TokenEnhancer/AccessTokenConverter)
@Bean
public DefaultTokenServices tokenServices() {
DefaultTokenServices services = new DefaultTokenServices();
services.setClientDetailsService(customClientDetailsService());
services.setSupportRefreshToken(true);
services.setTokenStore(tokenStore());
services.setTokenEnhancer(accessTokenConverter()); // 关联JWT转换器
services.setAccessTokenValiditySeconds(accessTokenExpire);
return services;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(customClientDetailsService()); //使用数据库客户端信息
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter())
.tokenServices(tokenServices()); //关联自定义令牌服务
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security
.allowFormAuthenticationForClients() //允许客户端表单认证
.tokenKeyAccess("permitAll()") //公开令牌密钥端点
.checkTokenAccess("isAuthenticated()"); //验证令牌需认证
}
}
java
package com.saas.study.config;
import com.saas.study.component.CustomAccessDeniedHandler;
import com.saas.study.component.CustomAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
/**
* 资源服务器配置:整合所有异常处理器
*/
@Configuration
@EnableAuthorizationServer
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
// 注入自定义处理器
@Autowired
private CustomAccessDeniedHandler customAccessDeniedHandler;
@Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
/**
* 配置资源服务器安全规则(异常处理)
*/
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
// 认证失败(401):令牌无效/过期等
.authenticationEntryPoint(customAuthenticationEntryPoint)
// 权限不足(403):已认证但无权限
.accessDeniedHandler(customAccessDeniedHandler);
}
/**
* 配置接口访问权限规则
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() //前后端分离关闭CSRF
.authorizeRequests()
//公开接口(无需认证)
.antMatchers("/user/tologin","/user/login").permitAll()
//管理员接口(需ADMIN角色)
.antMatchers("/admin/base/**").hasRole("ADMIN")
//用户接口(USER角色,支持多个)
.antMatchers("/user/base/**").hasAnyRole( "USER")
//其他所有接口需认证
.anyRequest().authenticated();
}
}
java
package com.saas.study.config;
import com.saas.study.component.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
/**
* security安全配置类
*/
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
//密码加密器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//认证管理器
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/oauth/**").permitAll() //开放OAuth相关端点
.anyRequest().authenticated()
.and()
.formLogin().permitAll(); //允许表单登录(可选)
}
}
6.在SpringBootStudyApplication添加注解@MapperScan扫描Mapper
java
package com.saas.study;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.saas.study.**.mapper")
public class SpringbootStudyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootStudyApplication.class, args);
}
}
7.打开类SpringBootStudyApplication,右键运行

8.打开postman调试
①.访问http://localhost:8888/user/login?username=saas&password=123456进行登录

②.访问http://localhost:8888/user/base/getUserInfoList 获取所有用户信息(请求头添加字段Authorization,值是Bearer+空格+第一步获取的access_token)

③.模拟当登录用户改成admin,再次访问获取所有用户接口时候的情况


9.下载地址
百度云:https://pan.baidu.com/s/1-N3CfbmhQZ5X8agKnGQXFw 提取码: nm7n