# security-enhance-spring-boot **Repository Path**: shangxiaopeng/security-enhance-spring-boot ## Basic Information - **Project Name**: security-enhance-spring-boot - **Description**: spring security 增强包 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 23 - **Created**: 2021-07-10 - **Last Updated**: 2022-05-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Security Spring Boot Starter 开箱即用,使用方法关注公众号:码农小胖哥 获取。 ## 使用前提 把我的Spring Security教程大致看一遍,会的就不用了,这样你会明白为什么这么干。 ## 使用方式 1. 集成**Spring Cache**。 2. 实现用户加载服务扩展接口`ChannelUserDetailsService`。 3. 实现用户角色权限方法`Function, Set>`。 4. 如果有特殊登录方式请实现对应的`LoginChannelProcessor`。 5. 标记`@EnableSpringSecurity`以启用配置。 ## 匿名权限 > 所有的资源都应该被角色管理,即使它是全量放开的。 如果希望特定的资源对用户全量开放,可配置对应的权限角色编码为`ANONYMOUS`。当某个资源的角色编码为`ANONYMOUS`时,即使不携带**Token**也可以访问。 ## 登录方式 ### 普通登录 ```http request POST /login?username=user&password=12345 HTTP/1.1 Host: localhost:8085 ``` ### 验证码登录 需要在Spring IoC对应的`LoginChannelProcessor`对象`CaptchaLoginChannelProcessor`。 发送验证码后调用验证码登录接口: ```http request POST /login/captcha?phone=11111111111&captcha=123123 HTTP/1.1 Host: localhost:8085 ``` ### 小程序登录 > 和验证码有点不一样 需要在Spring IoC对应的`LoginChannelProcessor`对象`MiniAppLoginChannelProcessor`。 这里的`clientId` 是对应查小程序`appid`和`secret`的东西,一个小程序就写死映射关系,多个的话还是持久化到数据库吧。 前端先调用微信授权登录接口获取`openid`: ```http request POST /miniapp/preauth?clientId=wxd14qr6&jsCode=051AOlFa19iRiB0LRZHa1tZ5yj3AOlFr HTTP/1.1 Host: localhost:8085 ``` 响应: ```json { "code": 200, "data": { "errcode": null, "errmsg": null, "sessionKey": null, "openid": "oWmZj5QBrZIBks0JDOUxRrZJi4", "unionid": "oS-dK520tgW84w_x7dA-h9MIuA" }, "msg": "", "identifier": true } ``` 这个时候`session_key`已经缓存了,参见`MiniAppPreAuthenticationFilter`逻辑,然后调用小程序登录接口: ```http request POST /login/miniapp HTTP/1.1 Host: localhost:8085 Content-Type: application/json { "clientId": "wxd14qr6", "openId": "oWmZj5QBrZIBks0JWD8OUxRrZJi4", "unionId": "oS-dK520tgW8yU4w_x7dA-h9MIuA", "iv":"LQUOt8BSTa7BWqAhqApe1Q==", "encryptedData": "10hn3o4zERB+F8MO4tvmM5CTah69wSRGlBBrO/Ag5nRD3QkLSzduKnWuzN9B/H47T8yaaqZsrMycLAoe2qrd1J75yYetYuWifiq3jUrcceRZHVxxl9LnQdW8f5+pMTnQtCYiMJ7Jm9paCw2Bh+5Lowkyqkx1q0fALvCQ9LXPPLAbLOB9CavRfKoenAmyyHQjZ/6lz0njzA==" } ``` > 有其它需求自己魔改,不算很难。 ## JWT ### JWT 密钥证书 利用Keytool工具生成,采用RSA算法的样例: ``` keytool -genkey -alias felord -keyalg RSA -storetype PKCS12 -keysize 2048 -validity 365 -keystore /path/keystores/jwt.jks -storepass 1asdfasdfaffdsa -dname "CN=(felord), OU=(felord), O=(felord), L=(zz), ST=(hn), C=(cn)" ``` ### JWT 示例 ``` eyJraWQiOiJuYXNoaSIsInR5cCI6QiOiJ1c2VyaWQiLCJpc3MiOiJodHRwczpcL1wvd3d3Lm5hc2hpLmNvbSIsImp0aSI6ImRhOWFhYmI2LWM0NmMtPica_Mvmx3jKChBgPEGq6hfleoNTFA6dg8mfYsuJlZ3jCpyYH96JnXOQSDY5F1g-J-zWpatoY_1gaxMywC5462__GHrdACSlbhNFdXr9nvbOAp68JNqfCkusOnr3Uj7ZGNgll4h-qccqjoZ9t6SgveNLgsjbuHGW57KDPVpQfUngYLoDwZcuPpGtYUfxsHn3yf427blg ``` ### 系统定义 JWT 对象示例 返回包含两个token主体 - `accessToken` 用来日常进行请求鉴权,有过期时间。 - `refreshToken` 当`accessToken`过期失效时,用来刷新`accessToken`。 ```json { "accessToken": { "tokenValue": "eyJraWQiOiJuYXNoaSIGdCVE7zQw", "issuedAt": { "epochSecond": 1616827822, "nano": 393000000 }, "expiresAt": { "epochSecond": 1616831422, "nano": 393000000 }, "tokenType": { "value": "Bearer" }, "scopes": [ "ROLE_ADMIN", "ROLE_APP" ] }, "refreshToken": { "tokenValue": "eyJraWQiOiJuYXNoaSIsInR5cCI", "issuedAt": { "epochSecond": 1616827822, "nano": 393000000 }, "expiresAt": null }, "additionalParameters": {} } ``` > `accessToken` 和 `refreshToken` 总是成对出现。 ### Bearer Token的使用 ```http request GET /user/1 HTTP/1.1 Host: localhost:8080 Authorization: Bearer eyJraWQiOiJuYXNoaSIsInR5cCI6IkpXVCI ```