mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 20:28:44 +08:00 
			
		
		
		
	增加 oauth2 的 scope 的校验方法,与使用示例
This commit is contained in:
		@@ -28,7 +28,7 @@ Content-Type: application/x-www-form-urlencoded
 | 
			
		||||
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
 | 
			
		||||
tenant-id: {{adminTenentId}}
 | 
			
		||||
 | 
			
		||||
grant_type=password&username=admin&password=admin123&scope=user_info
 | 
			
		||||
grant_type=password&username=admin&password=admin123&scope=user.read
 | 
			
		||||
 | 
			
		||||
### 请求 /system/oauth2/token + refresh_token 接口 => 成功
 | 
			
		||||
POST {{baseUrl}}/system/oauth2/token
 | 
			
		||||
@@ -47,3 +47,18 @@ tenant-id: {{adminTenentId}}
 | 
			
		||||
POST {{baseUrl}}/system/oauth2/check-token?token=620d307c5b4148df8a98dd6c6c547106
 | 
			
		||||
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
 | 
			
		||||
tenant-id: {{adminTenentId}}
 | 
			
		||||
 | 
			
		||||
### 请求 /system/oauth2/user/get 接口 => 成功
 | 
			
		||||
GET {{baseUrl}}/system/oauth2/user/get
 | 
			
		||||
Authorization: Bearer 9502bd7a768a4ade920b90f41e2efd5c
 | 
			
		||||
tenant-id: {{adminTenentId}}
 | 
			
		||||
 | 
			
		||||
### 请求 /system/oauth2/user/update 接口 => 成功
 | 
			
		||||
PUT {{baseUrl}}/system/oauth2/user/update
 | 
			
		||||
Content-Type: application/json
 | 
			
		||||
Authorization: Bearer 9502bd7a768a4ade920b90f41e2efd5c
 | 
			
		||||
tenant-id: {{adminTenentId}}
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
  "nickname": "芋道源码"
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.lang.Assert;
 | 
			
		||||
import cn.hutool.core.util.ArrayUtil;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
@@ -11,25 +12,35 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 | 
			
		||||
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserInfoRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2OpenConvert;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.enums.auth.OAuth2GrantTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.dept.DeptService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.dept.PostService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 | 
			
		||||
import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
 | 
			
		||||
import io.swagger.annotations.Api;
 | 
			
		||||
import io.swagger.annotations.ApiImplicitParam;
 | 
			
		||||
import io.swagger.annotations.ApiImplicitParams;
 | 
			
		||||
import io.swagger.annotations.ApiOperation;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.security.access.prepost.PreAuthorize;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import javax.validation.Valid;
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
@@ -40,7 +51,19 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 | 
			
		||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 | 
			
		||||
 | 
			
		||||
@Api(tags = "管理后台 - OAuth2.0 授权") // 提供给外部应用调用为主
 | 
			
		||||
/**
 | 
			
		||||
 * 提供给外部应用调用为主
 | 
			
		||||
 *
 | 
			
		||||
 * 一般来说,管理后台的 /system-api/* 是不直接提供给外部应用使用,主要是外部应用能够访问的数据与接口是有限的,而管理后台的 RBAC 无法很好的控制。
 | 
			
		||||
 * 参考大量的开放平台,都是独立的一套 OpenAPI,对应到【本系统】就是在 Controller 下新建 open 包,实现 /open-api/* 接口,然后通过 scope 进行控制。
 | 
			
		||||
 * 另外,一个公司如果有多个管理后台,它们 client_id 产生的 access token 相互之间是无法互通的,即无法访问它们系统的 API 接口,直到两个 client_id 产生信任授权。
 | 
			
		||||
 *
 | 
			
		||||
 * 考虑到【本系统】暂时不想做的过于复杂,默认只有获取到 access token 之后,可以访问【本系统】管理后台的 /system-api/* 所有接口,除非手动添加 scope 控制。
 | 
			
		||||
 * scope 的使用示例,可见当前类的 getUserInfo 和 updateUserInfo 方法,上面有 @PreAuthorize("@ss.hasScope('user.read')") 和 @PreAuthorize("@ss.hasScope('user.write')") 注解
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Api(tags = "管理后台 - OAuth2.0 授权")
 | 
			
		||||
@RestController
 | 
			
		||||
@RequestMapping("/system/oauth2")
 | 
			
		||||
@Validated
 | 
			
		||||
@@ -291,4 +314,43 @@ public class OAuth2OpenController {
 | 
			
		||||
        return clientIdAndSecret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // ============ 用户操作的示例,展示 scope 的使用 ============
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private AdminUserService userService;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private DeptService deptService;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PostService postService;
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/user/get")
 | 
			
		||||
    @ApiOperation("获得用户基本信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasScope('user.read')")
 | 
			
		||||
    public CommonResult<OAuth2OpenUserInfoRespVO> getUserInfo() {
 | 
			
		||||
        // 获得用户基本信息
 | 
			
		||||
        AdminUserDO user = userService.getUser(getLoginUserId());
 | 
			
		||||
        OAuth2OpenUserInfoRespVO resp = OAuth2OpenConvert.INSTANCE.convert(user);
 | 
			
		||||
        // 获得部门信息
 | 
			
		||||
        if (user.getDeptId() != null) {
 | 
			
		||||
            DeptDO dept = deptService.getDept(user.getDeptId());
 | 
			
		||||
            resp.setDept(OAuth2OpenConvert.INSTANCE.convert(dept));
 | 
			
		||||
        }
 | 
			
		||||
        // 获得岗位信息
 | 
			
		||||
        if (CollUtil.isNotEmpty(user.getPostIds())) {
 | 
			
		||||
            List<PostDO> posts = postService.getPosts(user.getPostIds());
 | 
			
		||||
            resp.setPosts(OAuth2OpenConvert.INSTANCE.convertList(posts));
 | 
			
		||||
        }
 | 
			
		||||
        return success(resp);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PutMapping("/user/update")
 | 
			
		||||
    @ApiOperation("更新用户基本信息")
 | 
			
		||||
    @PreAuthorize("@ss.hasScope('user.write')")
 | 
			
		||||
    public CommonResult<Boolean> updateUserInfo(@Valid @RequestBody UserProfileUpdateReqVO reqVO) {
 | 
			
		||||
        // 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。
 | 
			
		||||
        // 主要是,AdminUserService 没有自己的 BO 对象,所以复用只能这么做
 | 
			
		||||
        userService.updateUserProfile(getLoginUserId(), OAuth2OpenConvert.INSTANCE.convert(reqVO));
 | 
			
		||||
        return success(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,71 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@ApiModel("管理后台 - 【开放接口】获得用户基本信息 Response VO")
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public class OAuth2OpenUserInfoRespVO {
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户编号", required = true, example = "1")
 | 
			
		||||
    private Long id;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
 | 
			
		||||
    private String username;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户昵称", required = true, example = "芋道")
 | 
			
		||||
    private String nickname;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn")
 | 
			
		||||
    private String email;
 | 
			
		||||
    @ApiModelProperty(value = "手机号码", example = "15601691300")
 | 
			
		||||
    private String mobile;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SexEnum 枚举类")
 | 
			
		||||
    private Integer sex;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户头像", example = "https://www.iocoder.cn/xxx.png")
 | 
			
		||||
    private String avatar;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 所在部门
 | 
			
		||||
     */
 | 
			
		||||
    private Dept dept;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 所属岗位数组
 | 
			
		||||
     */
 | 
			
		||||
    private List<Post> posts;
 | 
			
		||||
 | 
			
		||||
    @ApiModel("部门")
 | 
			
		||||
    @Data
 | 
			
		||||
    public static class Dept {
 | 
			
		||||
 | 
			
		||||
        @ApiModelProperty(value = "部门编号", required = true, example = "1")
 | 
			
		||||
        private Long id;
 | 
			
		||||
 | 
			
		||||
        @ApiModelProperty(value = "部门名称", required = true, example = "研发部")
 | 
			
		||||
        private String name;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @ApiModel("岗位")
 | 
			
		||||
    @Data
 | 
			
		||||
    public static class Post {
 | 
			
		||||
 | 
			
		||||
        @ApiModelProperty(value = "岗位编号", required = true, example = "1")
 | 
			
		||||
        private Long id;
 | 
			
		||||
 | 
			
		||||
        @ApiModelProperty(value = "岗位名称", required = true, example = "开发")
 | 
			
		||||
        private String name;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,35 @@
 | 
			
		||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user;
 | 
			
		||||
 | 
			
		||||
import io.swagger.annotations.ApiModel;
 | 
			
		||||
import io.swagger.annotations.ApiModelProperty;
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
import org.hibernate.validator.constraints.Length;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.Email;
 | 
			
		||||
import javax.validation.constraints.Size;
 | 
			
		||||
 | 
			
		||||
@ApiModel("管理后台 - 【开放接口】更新用户基本信息 Request VO")
 | 
			
		||||
@Data
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public class OAuth2OpenUserUpdateReqVO {
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
 | 
			
		||||
    @Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
 | 
			
		||||
    private String nickname;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn")
 | 
			
		||||
    @Email(message = "邮箱格式不正确")
 | 
			
		||||
    @Size(max = 50, message = "邮箱长度不能超过 50 个字符")
 | 
			
		||||
    private String email;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "手机号码", example = "15601691300")
 | 
			
		||||
    @Length(min = 11, max = 11, message = "手机号长度必须 11 位")
 | 
			
		||||
    private String mobile;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SexEnum 枚举类")
 | 
			
		||||
    private Integer sex;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -46,7 +46,6 @@ public class UserProfileController {
 | 
			
		||||
    private AdminUserService userService;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private DeptService deptService;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PostService postService;
 | 
			
		||||
    @Resource
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,7 @@ import javax.validation.constraints.Size;
 | 
			
		||||
public class UserProfileUpdateReqVO {
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
 | 
			
		||||
    @Size(max = 30, message = "用户昵称长度不能超过30个字符")
 | 
			
		||||
    @Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
 | 
			
		||||
    private String nickname;
 | 
			
		||||
 | 
			
		||||
    @ApiModelProperty(value = "用户邮箱", example = "yudao@iocoder.cn")
 | 
			
		||||
 
 | 
			
		||||
@@ -4,11 +4,18 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserInfoRespVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 | 
			
		||||
import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
 | 
			
		||||
import org.mapstruct.Mapper;
 | 
			
		||||
import org.mapstruct.factory.Mappers;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Mapper
 | 
			
		||||
public interface OAuth2OpenConvert {
 | 
			
		||||
 | 
			
		||||
@@ -31,4 +38,12 @@ public interface OAuth2OpenConvert {
 | 
			
		||||
    }
 | 
			
		||||
    OAuth2OpenCheckTokenRespVO convert3(OAuth2AccessTokenDO bean);
 | 
			
		||||
 | 
			
		||||
    // ============ 用户操作的示例 ============
 | 
			
		||||
 | 
			
		||||
    OAuth2OpenUserInfoRespVO convert(AdminUserDO bean);
 | 
			
		||||
    OAuth2OpenUserInfoRespVO.Dept convert(DeptDO dept);
 | 
			
		||||
    List<OAuth2OpenUserInfoRespVO.Post> convertList(List<PostDO> list);
 | 
			
		||||
 | 
			
		||||
    UserProfileUpdateReqVO convert(UserProfileUpdateReqVO bean);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user