添加点常用的教程

This commit is contained in:
D 2024-01-10 18:52:08 +08:00
parent e2d7094419
commit c00a7c5375
2 changed files with 208 additions and 0 deletions

68
doc/权限控制.md Normal file
View File

@ -0,0 +1,68 @@
### 与权限有关的注解
`@Anonymous`注解用于配置公开接口
`@PreAuthorize`注解用于配置接口要求用户拥有某些权限才可访问,它拥有如下方法
| 方法 | 参数 | 描述 |
| ----------- | ------ | ---------------------------------------------- |
| hasPermi | String | 验证用户是否具备某权限 |
| lacksPermi | String | 验证用户是否不具备某权限,与 hasPermi逻辑相反 |
| hasAnyPermi | String | 验证用户是否具有以下任意一个权限 |
| hasRole | String | 判断用户是否拥有某个角色 |
| lacksRole | String | 验证用户是否不具备某角色,与 isRole逻辑相反 |
| hasAnyRoles | String | 验证用户是否具有以下任意一个角色,多个逗号分隔 |
```java
@PreAuthorize("@ss.hasPermi('system:user:list')")
@PreAuthorize("@ss.lacksPermi('system:user:list')")
@PreAuthorize("@ss.hasAnyPermi('system:user:add,system:user:edit')")
```
`@DataScope`注解用于配置接口数据权限
* `deptAlias`用于指定部门表的别名;
* `userAlias`用于指定用户表的别名;
* 实体需要继承BaseEntity类;
* `全部数据权限`、`自定数据权限`、`部门数据权限`、`部门及以下数据权限`、`仅本人数据权限`五种权限模式在后台角色管理界面配置数据权限
```java
// 部门数据权限注解
@DataScope(deptAlias = "d")
// 部门及用户权限注解
@DataScope(deptAlias = "d", userAlias = "u")
```
1. 使用注解
```java
@DataScope(deptAlias = "d", userAlias = "u")
public List<...> select(...)
{
return mapper.select(...);
}
```
2. 配置mybatis的xml
```xml
<select id="select" parameterType="..." resultMap="...Result">
<include refid="select...Vo"/>
<!-- 数据范围过滤 -->
${params.dataScope}
</select>
```
### 安全工具类
com.ruoyi.common.utils.SecurityUtils
| 方法 | 参数 | 返回 | 描述 |
| ------------ | ------ | ---------- | ------------------------ |
| getUserId | 无 | Long | 获取当前用户ID |
| getDeptId | 无 | Long | 获取当前部门ID |
| getUsername | 无 | String | 获取当前用户账户 |
| getLoginUser | 无 | LonginUser | 获取当前登录用户代理 |
| hasPermi | String | boolean | 验证用户是否具备某权限 |
| hasRole | String | boolean | 验证用户是否拥有某个角色 |

140
doc/登录+JWT逻辑.drawio Normal file
View File

@ -0,0 +1,140 @@
<mxfile host="65bd71144e">
<diagram id="IyeDk-cAWrKOq7F3gyWb" name="第 1 页">
<mxGraphModel dx="985" dy="704" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#000000" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="7" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="5" target="6">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="5" value="访问/login" style="html=1;" vertex="1" parent="1">
<mxGeometry x="304" y="60" width="110" height="50" as="geometry"/>
</mxCell>
<mxCell id="9" value="" style="edgeStyle=none;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="6" target="20">
<mxGeometry relative="1" as="geometry">
<mxPoint x="359.0000000000001" y="240" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="6" value="被SysLoginController.login()捕获" style="html=1;" vertex="1" parent="1">
<mxGeometry x="265.5" y="130" width="187" height="40" as="geometry"/>
</mxCell>
<mxCell id="20" value="&lt;span style=&quot;font-weight: 400;&quot;&gt;调用方法SysLoginService.login()执行登录逻辑&lt;/span&gt;" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="110" y="195" width="500" height="1075" as="geometry">
<mxRectangle x="109" y="195" width="290" height="30" as="alternateBounds"/>
</mxGeometry>
</mxCell>
<mxCell id="22" value="" style="edgeStyle=none;html=1;" edge="1" parent="20" source="10" target="21">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="10" value="调用方法SysLoginService.validateCaptcha()&lt;br&gt;1. &lt;font color=&quot;#00ffff&quot;&gt;从redis里拿到验证码对应的验证信息&lt;/font&gt;&lt;br&gt;2. &lt;font color=&quot;#00ffff&quot;&gt;删除redis中验证码对应的验证信息&lt;/font&gt;&lt;br&gt;3. 如果验证信息为空,&lt;font color=&quot;#ff0000&quot;&gt;抛出验证码过期的异常&lt;/font&gt;&lt;br&gt;4. 如果code与验证信息的值不同&lt;font color=&quot;#ff0000&quot;&gt;抛出验证码错误的异常&lt;/font&gt;" style="html=1;" vertex="1" parent="20">
<mxGeometry x="104.85" y="45" width="312.25" height="100" as="geometry"/>
</mxCell>
<mxCell id="24" value="" style="edgeStyle=none;html=1;" edge="1" parent="20" source="21" target="23">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="21" value="调用方法SysLoginService.loginPreCheck()&lt;br&gt;1. &lt;font color=&quot;#ff0000&quot;&gt;用户名或密码为空 -&amp;gt; 错误 抛出异常&lt;/font&gt;&lt;br&gt;2. &lt;font color=&quot;#ff0000&quot;&gt;密码不在指定范围内 -&amp;gt; 错误 抛出异常&lt;/font&gt;&lt;br&gt;3. &lt;font color=&quot;#ff0000&quot;&gt;用户名不在指定范围内 -&amp;gt; 错误 抛出异常&lt;/font&gt;&lt;br&gt;4. &lt;font color=&quot;#ff0000&quot;&gt;IP黑名单校验 -&amp;gt; 错误 抛出异常&lt;/font&gt;" style="html=1;" vertex="1" parent="20">
<mxGeometry x="104.85" y="170" width="312.25" height="100" as="geometry"/>
</mxCell>
<mxCell id="26" style="edgeStyle=none;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="20" source="23" target="25">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="23" value="&lt;font color=&quot;#00ff00&quot;&gt;通过new UsernamePasswordAuthenticationToken生成一个认证信息&lt;br&gt;通过AuthenticationContextHolder.setContext将认证信息设置到上下文&lt;/font&gt;&lt;br&gt;通过AuthenticationManager.authenticate()对认证信息进行认证,这个方法&lt;br&gt;会去调用UserDetailsServiceImpl.loadUserByUsername()方法进行认证" style="html=1;" vertex="1" parent="20">
<mxGeometry x="57.91" y="300" width="406.13" height="70" as="geometry"/>
</mxCell>
<mxCell id="39" value="" style="edgeStyle=none;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="20" source="25" target="40">
<mxGeometry relative="1" as="geometry">
<mxPoint x="261" y="785" as="sourcePoint"/>
<mxPoint x="245.01" y="805" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="25" value="&lt;span style=&quot;font-weight: 400;&quot;&gt;loadUserByUsername&lt;/span&gt;" style="swimlane;whiteSpace=wrap;html=1;" vertex="1" parent="20">
<mxGeometry x="41.94" y="385" width="438.06" height="390" as="geometry">
<mxRectangle x="25.97999999999999" y="380" width="160" height="30" as="alternateBounds"/>
</mxGeometry>
</mxCell>
<mxCell id="29" value="" style="edgeStyle=none;html=1;" edge="1" parent="25" source="27" target="28">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="27" value="调用ISysUserService.selectUserByUserName()获取用户信息&lt;br&gt;校验是否为空 -&amp;gt; &lt;font color=&quot;#ff0000&quot;&gt;抛出用户不存在的异常&lt;/font&gt;&lt;br&gt;校验是否已被删除 -&amp;gt; &lt;font color=&quot;#ff0000&quot;&gt;抛出用户已被删除的异常&lt;/font&gt;&lt;br&gt;校验是否已被停用 -&amp;gt; &lt;font color=&quot;#ff0000&quot;&gt;抛出用户已被停用的异常&lt;/font&gt;" style="whiteSpace=wrap;html=1;" vertex="1" parent="25">
<mxGeometry x="30.04" y="30" width="379.96" height="60" as="geometry"/>
</mxCell>
<mxCell id="28" value="调用SysPasswordService.validate()进行认证&lt;br&gt;1. 获取上下文的认证信息,并获取认证信息中携带的用户名和密码&lt;br&gt;2. &lt;font color=&quot;#00ffff&quot;&gt;从redis中获取该用户名密码错误次数&lt;/font&gt;&lt;br&gt;3. 校验该用户名密码错误次数是否过多&lt;br&gt;若次数过多,则&lt;font color=&quot;#ff0000&quot;&gt;抛出密码错误次数过多的异常&lt;/font&gt;&lt;br&gt;4. 调用SecurityUtils.matchesPassword方法校验用户名密码是否匹配&lt;br&gt;5. 若不匹配,则密码错误次数加一,且&lt;font color=&quot;#ff0000&quot;&gt;抛出密码错误的异常&lt;/font&gt;&lt;br&gt;否则清楚密码错误次数,校验结束即校验通过" style="whiteSpace=wrap;html=1;" vertex="1" parent="25">
<mxGeometry x="29.05" y="120" width="379.96" height="120" as="geometry"/>
</mxCell>
<mxCell id="36" value="调用createLoginUser方法new&amp;nbsp;LoginUser()创建一个UserDetails凭证&lt;br&gt;调用SysPermissionService.getMenuPermission()方法获取用户角色权限" style="html=1;" vertex="1" parent="25">
<mxGeometry x="15.960000000000008" y="275" width="406.13" height="70" as="geometry"/>
</mxCell>
<mxCell id="37" style="edgeStyle=none;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="25" source="28" target="36">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="44" value="" style="edgeStyle=none;html=1;" edge="1" parent="20" source="40" target="43">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="40" value="1. &lt;font color=&quot;#ff0000&quot;&gt;若上述环节抛出异常则处理异常并抛出对应的新的异常,校验环节结束&lt;/font&gt;&lt;br&gt;2. 无论校验结果如何,清除上下文" style="html=1;" vertex="1" parent="20">
<mxGeometry x="57.91" y="805" width="406.13" height="70" as="geometry"/>
</mxCell>
<mxCell id="43" value="1. 调用createToken()记录并更新用户信息&lt;br&gt;2. 调用TokenService.createToken()生成token&lt;br&gt;设置用户代理信息LoginUser将&lt;font color=&quot;#00ffff&quot;&gt;LoginUser存入redis&lt;/font&gt;" style="html=1;" vertex="1" parent="20">
<mxGeometry x="57.91" y="925" width="406.13" height="70" as="geometry"/>
</mxCell>
<mxCell id="45" style="edgeStyle=none;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="40" target="46">
<mxGeometry relative="1" as="geometry">
<mxPoint x="660" y="1055" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="46" value="认证失败" style="html=1;fontColor=#FF0000;labelBorderColor=none;strokeColor=#FF0000;" vertex="1" parent="1">
<mxGeometry x="660" y="1010" width="100" height="50" as="geometry"/>
</mxCell>
<mxCell id="47" style="edgeStyle=none;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="43" target="48">
<mxGeometry relative="1" as="geometry">
<mxPoint x="333.06500000000005" y="1330.0000000000002" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="65" value="" style="edgeStyle=none;html=1;fontColor=#00FFFF;" edge="1" parent="1" source="48" target="64">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="48" value="认证成功&lt;br&gt;将Token返回给前端" style="html=1;" vertex="1" parent="1">
<mxGeometry x="302.51" y="1300" width="136.93" height="80" as="geometry"/>
</mxCell>
<mxCell id="51" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="49" target="50">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="49" value="Token认证" style="whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="310.98" y="1570" width="120" height="60" as="geometry"/>
</mxCell>
<mxCell id="53" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="50" target="52">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="50" value="触发JwtAuthenticationTokenFilter拦截器&lt;br&gt;调用doFilterInternal方法进行处理" style="whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="235.98" y="1690" width="270" height="60" as="geometry"/>
</mxCell>
<mxCell id="55" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="52" target="54">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="52" value="调用TokenService.getLoginUser()方法&lt;br&gt;1. 调用方法getToken从request的请求头中获取token&lt;br&gt;&lt;font color=&quot;#00ffff&quot;&gt;2. 通过token在redis中获取用户代理信息LoginUser&lt;/font&gt;" style="whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="185.98" y="1780" width="370" height="60" as="geometry"/>
</mxCell>
<mxCell id="57" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="54" target="56">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="54" value="判断用户凭证是非空并且判断上下文认证信息为空&lt;br&gt;调用TokenService.verifyToken()校验token并判断最小时间刷新token" style="whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="175.98" y="1860" width="390" height="60" as="geometry"/>
</mxCell>
<mxCell id="59" value="" style="edgeStyle=none;html=1;" edge="1" parent="1" source="56" target="58">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="56" value="&lt;font color=&quot;#00ff00&quot;&gt;1. 通过UsernamePasswordAuthenticationToken创建一个认证信息&lt;br&gt;2. 通过WebAuthenticationDetailsSource构建一个用户凭证并通过UsernamePasswordAuthenticationToken.setDetails设置到认证信息里&lt;br&gt;3. 将认证信息通过SecurityContextHolder.getContext().setAuthentication&lt;br&gt;拿到上下文并设置到上下文&lt;/font&gt;" style="whiteSpace=wrap;html=1;strokeColor=#00FF00;" vertex="1" parent="1">
<mxGeometry x="161.45999999999998" y="1950" width="419.02" height="80" as="geometry"/>
</mxCell>
<mxCell id="58" value="继续过滤&lt;br&gt;在鉴权系统中会用到上述设置的上下文" style="whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="300.98" y="2060" width="140" height="60" as="geometry"/>
</mxCell>
<mxCell id="66" style="edgeStyle=none;html=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;fontColor=#00FFFF;" edge="1" parent="1" source="64" target="49">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="64" value="前端拿到token后存到浏览器中&lt;br&gt;后续发送请求在浏览器中拿到token&lt;br&gt;并将token设置到请求头里" style="whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="251.46" y="1430" width="239.02" height="90" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>