|
| 1 | +## ApiBoot Security Oauth |
| 2 | + |
| 3 | +### 引入 ApiBoot Security Oauth |
| 4 | + |
| 5 | +在`pom.xml`配置文件内添加如下: |
| 6 | + |
| 7 | +```xml |
| 8 | +<!--ApiBoot Security Oauth--> |
| 9 | +<dependency> |
| 10 | + <groupId>org.minbox.framework</groupId> |
| 11 | + <artifactId>api-boot-starter-security-oauth-jwt</artifactId> |
| 12 | +</dependency> |
| 13 | +``` |
| 14 | + |
| 15 | +> `ApiBoot`所提供的依赖都不需要添加版本号,但是需要添加版本依赖,具体查看[ApiBoot版本依赖](https://github.com/hengboy/api-boot/blob/master/README.md#%E6%B7%BB%E5%8A%A0%E7%89%88%E6%9C%AC%E4%BE%9D%E8%B5%96) |
| 16 | +
|
| 17 | +### 配置参数列表 |
| 18 | + |
| 19 | +`ApiBoot`在整合`SpringSecurity`、`Oauth2`时把配置参数进行了分离,配置列表如下所示: |
| 20 | + |
| 21 | +#### 整合SpringSecurity配置列表 |
| 22 | + |
| 23 | +| 配置名称 | 介绍 | 默认值 | 生效方式 | |
| 24 | +| ------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ----------- | |
| 25 | +| `api.boot.security.away` | SpringSecurity读取用户的方式,默认为内存方式 | memory | all | |
| 26 | +| `api.boot.security.auth-prefix` | 拦截的接口路径前缀,如:/api/users就会被默认拦截 | /api/** | memory/jdbc | |
| 27 | +| `api.boot.security.users` | 配置用户列表,具体使用查看[内存方式介绍]() | 无 | memory | |
| 28 | +| `api.boot.security.ignoring-urls` | `Spring Security`所排除的路径,默认排除Swagger、Actuator相关路径前缀 | /v2/api-docs<br />/swagger-ui.html<br />/swagger-resources/configuration/security<br />/META-INF/resources/webjars/**<br />/swagger-resources<br />/swagger-resources/configuration/ui<br />/actuator/** | memory/jdbc | |
| 29 | +| `api.boot.security.enable-default-store-delegate` | 仅在Jdbc方式生效 | true | jdbc | |
| 30 | + |
| 31 | + |
| 32 | + |
| 33 | +#### 整合Oauth2配置列表 |
| 34 | + |
| 35 | +| 配置名称 | 介绍 | 默认值 | 绑定away | |
| 36 | +| ------------------------------ | ---------------------------------- | --------------------- | ----------- | |
| 37 | +| `api.boot.oauth.away` | Oauth存储Token、读取Client信息方式 | memory | all | |
| 38 | +| `api.boot.oauth.cleint-id` | Oauth2 Client ID | ApiBoot | memory | |
| 39 | +| `api.boot.oauth.client-secret` | Oauth2 Client Secret | ApiBootSecret | memory | |
| 40 | +| `api.boot.oauth.grant-types` | 客户端授权方式 | Srtring[]{"password"} | memory | |
| 41 | +| `api.boot.oauth.scopes` | 客户端作用域 | String[]{"api"} | memory | |
| 42 | +| `api.boot.oauth.jwt.enable` | 是否启用JWT格式化AccessToken | false | memory/jdbc | |
| 43 | +| `api.boot.oauth.jwt.sign-key` | 使用JWT格式化AccessToken时的签名 | ApiBoot | memory/jdbc | |
| 44 | + |
| 45 | +`ApiBoot`在整合`SpringSecurity`、`Oauth2`时配置进行了分离,也就意味着我们可以让`SpringSecurity`读取内存用户、`Oauth2`将生成的`AccessToken`存放到`数据库`,当然反过来也是可以的,相互不影响!!! |
| 46 | + |
| 47 | +### 内存方式(默认方式) |
| 48 | + |
| 49 | +#### Spring Security |
| 50 | + |
| 51 | +`ApiBoot`在整合`Spring Security`的内存方式时,仅仅需要配置`api.boot.security.users`用户列表参数即可,就是这么的简单, |
| 52 | + |
| 53 | +配置用户示例如下所示: |
| 54 | + |
| 55 | +```yaml |
| 56 | +api: |
| 57 | + boot: |
| 58 | + security: |
| 59 | + # Spring Security 内存方式用户列表示例 |
| 60 | + users: |
| 61 | + - username: hengboy |
| 62 | + password: 123456 |
| 63 | + - username: apiboot |
| 64 | + password: abc321 |
| 65 | +``` |
| 66 | +
|
| 67 | +`api.boot.security.users`是一个`List<SecurityUser>`类型的集合,所以这里可以配置多个用户。 |
| 68 | + |
| 69 | +#### Oauth2 |
| 70 | + |
| 71 | +如果全部使用默认值的情况话不需要做任何配置!!! |
| 72 | + |
| 73 | +### Jdbc方式 |
| 74 | + |
| 75 | +> 前提:项目需要添加数据源依赖。 |
| 76 | + |
| 77 | +#### Spring Security |
| 78 | + |
| 79 | +**默认用户表** |
| 80 | + |
| 81 | +`ApiBoot`在整合`Spring Security`的Jdbc方式时,在使用`ApiBoot`提供的默认结构用户表时只需要修改`api.boot.security.away: jdbc`即可,`ApiBoot`提供的用户表结构如下所示: |
| 82 | + |
| 83 | +```sql |
| 84 | +CREATE TABLE `api_boot_user_info` ( |
| 85 | + `UI_ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户编号,主键自增', |
| 86 | + `UI_USER_NAME` varchar(30) DEFAULT NULL COMMENT '用户名', |
| 87 | + `UI_NICK_NAME` varchar(50) DEFAULT NULL COMMENT '用户昵称', |
| 88 | + `UI_PASSWORD` varchar(255) DEFAULT NULL COMMENT '用户密码', |
| 89 | + `UI_EMAIL` varchar(30) DEFAULT NULL COMMENT '用户邮箱地址', |
| 90 | + `UI_AGE` int(11) DEFAULT NULL COMMENT '用户年龄', |
| 91 | + `UI_ADDRESS` varchar(200) DEFAULT NULL COMMENT '用户地址', |
| 92 | + `UI_IS_LOCKED` char(1) DEFAULT 'N' COMMENT '是否锁定', |
| 93 | + `UI_IS_ENABLED` char(1) DEFAULT 'Y' COMMENT '是否启用', |
| 94 | + `UI_STATUS` char(1) DEFAULT 'O' COMMENT 'O:正常,D:已删除', |
| 95 | + `UI_CREATE_TIME` timestamp NULL DEFAULT current_timestamp() COMMENT '用户创建时间', |
| 96 | + PRIMARY KEY (`UI_ID`) |
| 97 | +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='ApiBoot默认的用户信息表'; |
| 98 | +``` |
| 99 | + |
| 100 | +**自定义用户表** |
| 101 | + |
| 102 | +如果你的系统已经存在了自定义用户表结构,`ApiBoot`是支持的,而且很简单就可以完成整合,我们需要先修改`api.boot.security.enable-default-store-delegate`参数为`false`,如下所示: |
| 103 | + |
| 104 | +```yaml |
| 105 | +api: |
| 106 | + boot: |
| 107 | + security: |
| 108 | + # Spring Security jdbc方式用户列表示例 |
| 109 | + enable-default-store-delegate: false |
| 110 | + away: jdbc |
| 111 | +``` |
| 112 | +
|
| 113 | +添加`ApiBootStoreDelegate`接口实现类,如下所示: |
| 114 | + |
| 115 | +```java |
| 116 | +@Component |
| 117 | +public class DisableDefaultUserTableStoreDelegate implements ApiBootStoreDelegate { |
| 118 | +
|
| 119 | + @Autowired |
| 120 | + private PasswordEncoder passwordEncoder; |
| 121 | +
|
| 122 | + /** |
| 123 | + * 用户列表示例 |
| 124 | + * 从该集合内读取用户信息 |
| 125 | + * 可以使用集合内的用户获取access_token |
| 126 | + */ |
| 127 | + static List<String> users = new ArrayList() { |
| 128 | + { |
| 129 | + add("api-boot"); |
| 130 | + add("hengboy"); |
| 131 | + add("yuqiyu"); |
| 132 | + } |
| 133 | + }; |
| 134 | +
|
| 135 | + /** |
| 136 | + * 根据用户名查询用户信息 |
| 137 | + * |
| 138 | + * @param username 用户名 |
| 139 | + * @return |
| 140 | + * @throws UsernameNotFoundException |
| 141 | + */ |
| 142 | + @Override |
| 143 | + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { |
| 144 | + if (!users.contains(username)) { |
| 145 | + throw new UsernameNotFoundException("用户:" + username + "不存在"); |
| 146 | + } |
| 147 | + return new DisableDefaultUserDetails(username); |
| 148 | + } |
| 149 | +
|
| 150 | + @Data |
| 151 | + @AllArgsConstructor |
| 152 | + @NoArgsConstructor |
| 153 | + class DisableDefaultUserDetails implements UserDetails { |
| 154 | + private String username; |
| 155 | +
|
| 156 | + @Override |
| 157 | + public Collection<? extends GrantedAuthority> getAuthorities() { |
| 158 | + return new ArrayList() { |
| 159 | + { |
| 160 | + add((GrantedAuthority) () -> "ROLE_USER"); |
| 161 | + } |
| 162 | + }; |
| 163 | + } |
| 164 | +
|
| 165 | + /** |
| 166 | + * 示例密码使用123456 |
| 167 | + * |
| 168 | + * @return |
| 169 | + */ |
| 170 | + @Override |
| 171 | + public String getPassword() { |
| 172 | + return passwordEncoder.encode("123456"); |
| 173 | + } |
| 174 | +
|
| 175 | + @Override |
| 176 | + public String getUsername() { |
| 177 | + return username; |
| 178 | + } |
| 179 | +
|
| 180 | + @Override |
| 181 | + public boolean isAccountNonExpired() { |
| 182 | + return true; |
| 183 | + } |
| 184 | +
|
| 185 | + @Override |
| 186 | + public boolean isAccountNonLocked() { |
| 187 | + return true; |
| 188 | + } |
| 189 | +
|
| 190 | + @Override |
| 191 | + public boolean isCredentialsNonExpired() { |
| 192 | + return true; |
| 193 | + } |
| 194 | +
|
| 195 | + @Override |
| 196 | + public boolean isEnabled() { |
| 197 | + return true; |
| 198 | + } |
| 199 | + } |
| 200 | +} |
| 201 | +``` |
| 202 | + |
| 203 | +根据上面代码示例,我们可以通过`users`用户列表进行访问获取`access_token`。 |
| 204 | + |
| 205 | + |
| 206 | + |
| 207 | +#### Oauth2 |
| 208 | + |
| 209 | +**创建Oauth所需表结构** |
| 210 | + |
| 211 | +`Oauth2`如果使用`Jdbc`方式进行存储`access_token`、`client_details`时,需要在数据库内初始化`Oauth2`所需相关表结构,[oauth-mysql.sql](https://github.com/hengboy/api-boot/tree/master/api-boot-project/api-boot-starters/api-boot-starter-security-oauth-jwt/oauth-mysql.sql) |
| 212 | + |
| 213 | +**添加客户端数据** |
| 214 | + |
| 215 | +初始化`Oauth2`表结构后,需要向`oauth_client_details`表内添加一个客户端信息,下面是对应`ApiBoot Security Oauth`配置信息的数据初始化,如下所示: |
| 216 | + |
| 217 | +```sql |
| 218 | +INSERT INTO `oauth_client_details` VALUES ('ApiBoot','api','$2a$10$M5t8t1fHatAj949RCHHB/.j1mrNAbxIz.mOYJQbMCcSPwnBMJLmMK','api','password',NULL,NULL,7200,7200,NULL,NULL); |
| 219 | +``` |
| 220 | + |
| 221 | +> `AppSecret`加密方式统一使用`BCryptPasswordEncoder`,数据初始化时需要注意。 |
| 222 | +
|
| 223 | + |
| 224 | + |
| 225 | +在上面`memory/jdbc`两种方式已经配置完成,接下来我们就可以获取`access_token`。 |
| 226 | + |
| 227 | +### 获取AccessToken |
| 228 | + |
| 229 | +#### 通过CURL获取 |
| 230 | + |
| 231 | +```sh |
| 232 | +➜ ~ curl ApiBoot:ApiBootSecret@localhost:8080/oauth/token -d "grant_type=password&username=api-boot&password=123456" |
| 233 | + |
| 234 | +{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTMxMDk1MjMsInVzZXJfbmFtZSI6ImFwaS1ib290IiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9VU0VSIl0sImp0aSI6IjBmZTUyY2RlLTBhZjctNDI1YS04Njc2LTFkYTUyZTA0YzUxYiIsImNsaWVudF9pZCI6IkFwaUJvb3QiLCJzY29wZSI6WyJhcGkiXX0.ImqGZssbDEOmpf2lQZjLQsch4ukE0C4SCYJsutfwfx0","token_type":"bearer","expires_in":42821,"scope":"api","jti":"0fe52cde-0af7-425a-8676-1da52e04c51b"} |
| 235 | +``` |
| 236 | + |
| 237 | + |
| 238 | + |
| 239 | +### 启用JWT |
| 240 | + |
| 241 | +`ApiBoot Security Oauth`在使用`JWT`格式化`access_token`时非常简单的,配置如下所示: |
| 242 | + |
| 243 | +```yaml |
| 244 | +api: |
| 245 | + boot: |
| 246 | + oauth: |
| 247 | + jwt: |
| 248 | + # 开启Jwt转换AccessToken |
| 249 | + enable: true |
| 250 | + # 转换Jwt时所需加密key,默认为ApiBoot |
| 251 | + sign-key: 恒宇少年 - 于起宇 |
| 252 | +``` |
| 253 | +
|
| 254 | +默认不启用`JWT`,`sign-key`签名建议进行更换。 |
0 commit comments