本文涉及知识点
使用Spring Boot 作为项目骨架,随后会出一篇使用Spring Cloud将这些技术点进行整合。前者更适合小型项目或练习用,后者更适合在中大型项目中部署使用。
该项目已开源到GitHub传送门。这篇文章会尽可能详细的讲解每一个步骤,若做不出来或有问题可以去GitHub下载本项目的源码或私信作者。
config : 配置包,用于配置OAuth,Security, JWT
controller:外部可请求的资源
dao:数据持久层
entity:实体类
service:业务层
util:工具包
user_db:数据库文件
可以在创建项目时进行勾选,可以直接复制pom文件中的坐标
版本:
使用 spring-cloud-starter-oauth2 可以省去很多引其他包的步骤,尽量避免由于版本造成的问题报错。
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.aaagroupId>
<artifactId>springboot-security-oauth2artifactId>
<version>0.0.1-SNAPSHOTversion>
<name>springboot-security-oauth2name>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASEspring-boot.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-oauth2artifactId>
<version>2.2.1.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>${spring-boot.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>2.3.0.RELEASEversion>
plugin>
plugins>
build>
project>
在这里对web、DataSource、MyBatis、Redis进行配置
注意:pom.xml中对于jdbc驱动引用在spring.datasource.driver-class-name对应的值不同,一定要根据自己在pom文件选择的jdbc驱动版本选择driver-class-name。
# web
server.port=8080
server.servlet.context-path=/
spring.application.name=security-springboot
# DataSource
spring.datasource.url=jdbc:mysql://localhost:3306/user_db
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
#logging.level.root=debug
# redis
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=0
这里与通常使用mybatis连接数据库方式相同。不难但步骤较多
user_db.sql
-- ----------------------------
-- Table structure for t_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (
`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`code` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限标识符',
`description` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
`url` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求地址',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ('1', 'p1', '测试资源\r\n1', '/resource/r1');
INSERT INTO `t_permission` VALUES ('2', 'p2', '测试资源2', '/resource/r2');
INSERT INTO `t_permission` VALUES ('3', 'p3', '测试资源3', '/resource/r3');
-- ----------------------------
-- Table structure for t_role
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`create_time` datetime(0) NULL DEFAULT NULL,
`update_time` datetime(0) NULL DEFAULT NULL,
`status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `unique_role_name`(`role_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', '管理员', NULL, NULL, NULL, '');
-- ----------------------------
-- Table structure for t_role_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_role_permission`;
CREATE TABLE `t_role_permission` (
`role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`permission_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`role_id`, `permission_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_role_permission
-- ----------------------------
INSERT INTO `t_role_permission` VALUES ('1', '1');
INSERT INTO `t_role_permission` VALUES ('1', '2');
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`fullname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户姓名',
`mobile` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'zhangsan', '$2a$10$37vdSYJUVguwXpLDnZfEt.UDC0y6Yk2RCzFuJKfOrWCiTnUFlmj3K', NULL, NULL);
INSERT INTO `t_user` VALUES (2, 'aaa', '$2a$10$UDvMFn8koZzJ70JGriqkbeVBELa.EFnFDFfkglZfiYhUyxryK3ebi', NULL, NULL);
INSERT INTO `t_user` VALUES (3, 'bbb', '$2a$10$eLA6kZcUI2PLvwX9n4unwe4hNZWlVBR5JuJ1fOQaHz9qnFxs.1jS.', NULL, NULL);
-- ----------------------------
-- Table structure for t_user_role
-- ----------------------------
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (
`user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
`create_time` datetime(0) NULL DEFAULT NULL,
`creator` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`user_id`, `role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of t_user_role
-- ----------------------------
INSERT INTO `t_user_role` VALUES ('1', '1', NULL, NULL);
SET FOREIGN_KEY_CHECKS = 1;
User.java
package com.aaa.entity;
/**
* 用户信息
* @author 淮南King
*/
public class User {
/**
* 用户id
*/
private String id;
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
/**
* 用户角色ID
*/
private Integer roleId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
}
Permission.java
package com.aaa.entity;
/**
* 权限信息
* @author 淮南King
*/
public class Permission {
/**
* 权限id
*/
private String id;
/**
* 权限代号
*/
private String code;
/**
* 权限描述
*/
private String description;
/**
* 路径
*/
private String url;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
UserDao.java
package com.aaa.dao;
import com.aaa.entity.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 用户信息持久层
* @author 淮南King
*/
@Mapper
public interface UserDao {
/**
* 根据账号查询用户信息
*
* @param username 用户姓名
* @return 用户信息
*/
User getUserByUsername(String username);
/**
* 根据用户id查询用户权限
*
* @param userId 用户id
* @return 权限列表
*/
List<String> findPermissionsByUserId(String userId);
}
UserService.java
package com.aaa.service;
import com.aaa.dao.UserDao;
import com.aaa.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 用户信息持久业务层
*
* @author 淮南King
* @date 2020-07-21
*/
@Service
public class UserService {
@Autowired UserDao dao;
public User getUserByUsername(String username) {
return dao.getUserByUsername(username);
}
public List<String> findPermissionsByUserId(String userId) {
return dao.findPermissionsByUserId(userId);
}
}
UserMapper.xml
<mapper namespace="com.aaa.dao.UserDao">
<select id="getUserByUsername" parameterType="String" resultType="com.aaa.entity.User">
select id,username,password,fullname,mobile from t_user where username = #{username}
select>
<select id="findPermissionsByUserId" parameterType="String" resultType="String">
SELECT code FROM t_permission WHERE id IN(
SELECT permission_id FROM t_role_permission WHERE role_id IN(
SELECT role_id FROM t_user_role WHERE user_id = #{id} ))
select>
mapper>
UserDetail.java
package com.aaa.config;
import com.aaa.dao.UserDao;
import com.aaa.entity.User;
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.List;
/**
* 实现spring-security核心接口UserDetailsService
* 负载用户特定数据
*
* @author 淮南King
*/
@Service
public class UserDetail implements UserDetailsService {
@Autowired UserDao userDao;
/**
* 根据账号查询用户信息
* @param username
* @return
*/
@Override public UserDetails loadUserByUsername(String username) {
//将来连接数据库根据账号查询用户信息
User user = userDao.getUserByUsername(username);
//当查询此用户不存在时,将抛出用户名未找到异常
if (user == null) {
throw new UsernameNotFoundException("No such user found, the user name is: "+username);
}
//根据用户id查询权限
List<String> permissions = userDao.findPermissionsByUserId(user.getId());
//将permissions转为数组
String[] permissionArray = new String[permissions.size()];
permissions.toArray(permissionArray);
//创建UserDetails 将从数据库查询到的用户信息包装返回给Security
UserDetails userDetails =
org.springframework.security.core.userdetails.User.withUsername(user.getUsername()).password(user.getPassword()).authorities(permissionArray)
.build();
return userDetails;
}
}
WebSecurityConfig.java
package com.aaa.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* spring security配置
* Order -> 指定优先级别 值越低,优先级越高。值越高,优先级越低
* EnableGlobalMethodSecurity 启用全局方法安全,启用pre注解
* @author 淮南King
*/
@Configuration
@Order(10)
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 密码编码器
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* 认证管理器
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 安全拦截机制
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//关闭跨域伪造请求拦截
http.csrf().disable();
//开启授权配置
http.authorizeRequests()
//允许访问授权接口
.antMatchers("/login/**","/oauth/**").permitAll()
//其他所有请求直接放行,权限验证在资源服务器中进行
.anyRequest().permitAll();
//允许表单登录
http.formLogin().permitAll();
}
}
TokenConfig.java
package com.aaa.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
/**
* Token 配置类
* @author 淮南King
* @date 2020-08-06
*/
@Configuration
public class TokenConfig {
/**
* 签名密钥
*/
private String SIGNING_KEY = "secret";
/**
* token存储
* @return
*/
@Bean
public TokenStore tokenStore() {
//JWT令牌存储方案
return new JwtTokenStore(accessTokenConverter());
}
/**
* Jwt访问令牌转换器
* @return
*/
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
//对称秘钥,资源服务器使用该秘钥来验证
converter.setSigningKey(SIGNING_KEY);
return converter;
}
}
MyAuthorizationServerConfig.java
package com.aaa.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
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.redis.RedisTokenStore;
import java.util.Arrays;
/**
* 认证服务器
*
* @author 淮南King
* @date 2020-08-04
*/
@Configuration
@EnableAuthorizationServer
public class MyAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired private RedisConnectionFactory redisConnectionFactory;
@Autowired private ClientDetailsService clientDetailsService;
@Autowired private AuthenticationManager authenticationManager;
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
/**
* 客户端详情服务
*
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 使用in-memory存储
clients.inMemory()
// client_id
.withClient("c1")
//客户端密钥
.secret(new BCryptPasswordEncoder().encode("secret"))
//资源列表
.resourceIds("res1")
// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
// 允许的授权范围
.scopes("all")
//false跳转到授权页面
.autoApprove(false)
//加上验证回调地址
.redirectUris("http://www.baidu.com");
}
/**
* 设置token存储在redis中
* @return
*/
@Bean
public TokenStore redisTokenStore() {
//使用redis存储token
RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
//设置redis token存储中的前缀
redisTokenStore.setPrefix("auth-token:");
return redisTokenStore;
}
/**
* 令牌管理服务
*
* @return
*/
@Bean
@Primary
public AuthorizationServerTokenServices tokenService() {
DefaultTokenServices service = new DefaultTokenServices();
//客户端详情服务
service.setClientDetailsService(clientDetailsService);
//支持刷新令牌
service.setSupportRefreshToken(true);
//令牌存储服务
service.setTokenStore(redisTokenStore());
//令牌增强
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
service.setTokenEnhancer(tokenEnhancerChain);
// 令牌默认有效期2小时
service.setAccessTokenValiditySeconds(7200);
// 刷新令牌默认有效期3天
service.setRefreshTokenValiditySeconds(259200);
return service;
}
@Autowired private AuthorizationCodeServices authorizationCodeServices;
//授权码模式 需要配置
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
//设置授权码模式的授权码如何存取
return new InMemoryAuthorizationCodeServices();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
//令牌管理服务
.tokenServices(tokenService())
//配置JWT转换器
.accessTokenConverter(accessTokenConverter)
//认证管理器
.authenticationManager(authenticationManager)
//授权码服务
.authorizationCodeServices(authorizationCodeServices)
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security
//oauth/token_key是公开
.tokenKeyAccess("permitAll()")
//oauth/check_token公开
.checkTokenAccess("permitAll()")
//表单认证(申请令牌)
.allowFormAuthenticationForClients();
}
}
MyResourceServerConfig.java
package com.aaa.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
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.oauth2.provider.error.OAuth2AccessDeniedHandler;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
/**
* 资源服务器
*
* @author 淮南King
* @date 2020-08-04
*/
@Configuration
@Order(2)
@EnableResourceServer
public class MyResourceServerConfig extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "res1";
/**
* 资源服务令牌解析服务
* @return
*/
@Bean
public ResourceServerTokenServices resourceTokenService() {
//使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
RemoteTokenServices service=new RemoteTokenServices();
service.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");
service.setClientId("c1");
service.setClientSecret("secret");
return service;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID)
.tokenServices(resourceTokenService())
.stateless(true);
}
/**
* 资源访问安全配置
* @param http
* @throws Exception
*/
@Override
public void configure(HttpSecurity http) throws Exception {
//关闭跨站请求防护
http.csrf().disable();
http
.authorizeRequests()
// '/oauth/token' 请求进行直接放行
.antMatchers("/oauth/token").permitAll()
// '/resource/**' 资源需要有all 范围
.antMatchers("/resource/**").access("#oauth2.hasScope('all')")
// 其他的资源进行放行
.anyRequest().permitAll();
//指定要使用的访问拒绝处理程序 OAuth2发送403
http.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
AuthController.java
package com.aaa.controller;
import com.aaa.util.SecurityUtil;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 需要权限才能被访问的资源
* @author 淮南King
* @date 2020-07-21
*/
@RestController
@RequestMapping("/resource")
public class AuthController {
/**
* 测试资源1
* 拥有p1权限才可以访问
*
* @return
*/
@GetMapping("/r1")
@PreAuthorize("hasAuthority('p1')")
public String resource1() {
//获取当前线程的SecurityContext
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
//获取当前线程的名称
return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源1";
}
/**
* 测试资源2
* 拥有p2权限才可以访问
*
* @return
*/
@GetMapping("/r2")
@PreAuthorize("hasAuthority('p2')")
public String resource2() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源2";
}
/**
* 测试资源3
* 拥有p3权限才可以访问
*
* @return
*/
@GetMapping("/r3")
@PreAuthorize("hasAuthority('p3')")
public String resource3() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源3";
}
}
TestController.java
package com.aaa.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 淮南King
*/
@RestController
public class TestController {
@GetMapping("test")
public String test(){
return "test访问成功,这个不需要权限哦!";
}
}
http://localhost:8080/oauth/token? client_id=c1&client_secret=secret&grant_type=password&username=shangsan&password=123
使用post请求后可以获取到token