重新制定规则,原来叫oauth模块不合适,应该叫auth模块,里面分为tfa双因素认证和oauth2.0第三方认证

This commit is contained in:
Dftre 2024-06-10 03:42:47 +08:00
parent 57ca64b0f7
commit 9a289e2f9e
52 changed files with 923 additions and 959 deletions

View File

@ -1,6 +1,6 @@
<mxfile host="65bd71144e"> <mxfile host="65bd71144e">
<diagram id="OUCQybPowJdnNh2YIqGc" name="第 1 页"> <diagram id="OUCQybPowJdnNh2YIqGc" name="第 1 页">
<mxGraphModel dx="880" dy="766" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> <mxGraphModel dx="823" dy="766" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root> <root>
<mxCell id="0"/> <mxCell id="0"/>
<mxCell id="1" parent="0"/> <mxCell id="1" parent="0"/>
@ -179,7 +179,7 @@
<mxPoint x="-12" y="16" as="offset"/> <mxPoint x="-12" y="16" as="offset"/>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="43" value="" style="edgeStyle=orthogonalEdgeStyle;html=1;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;connectable=1;entryX=1;entryY=0.25;entryDx=0;entryDy=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;" edge="1" parent="1" source="27" target="8"> <mxCell id="43" value="" style="edgeStyle=orthogonalEdgeStyle;html=1;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;movable=1;resizable=1;rotatable=1;deletable=1;editable=1;connectable=1;entryX=1;entryY=0.25;entryDx=0;entryDy=0;exitX=0;exitY=0.25;exitDx=0;exitDy=0;" parent="1" source="27" target="8" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<mxPoint x="442" y="640" as="targetPoint"/> <mxPoint x="442" y="640" as="targetPoint"/>
<mxPoint x="539" y="500" as="sourcePoint"/> <mxPoint x="539" y="500" as="sourcePoint"/>
@ -189,29 +189,29 @@
</Array> </Array>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="44" value="撤销申请退款" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="43"> <mxCell id="44" value="拒绝退款" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="43" vertex="1" connectable="0">
<mxGeometry x="0.2333" relative="1" as="geometry"> <mxGeometry x="0.2333" relative="1" as="geometry">
<mxPoint x="12" as="offset"/> <mxPoint x="12" as="offset"/>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="45" value="" style="edgeStyle=orthogonalEdgeStyle;html=1;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;" edge="1" parent="1" source="14" target="8"> <mxCell id="45" value="" style="edgeStyle=orthogonalEdgeStyle;html=1;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;entryX=0;entryY=0.75;entryDx=0;entryDy=0;exitX=1;exitY=0.75;exitDx=0;exitDy=0;" parent="1" source="14" target="8" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<mxPoint x="349" y="610" as="targetPoint"/> <mxPoint x="349" y="610" as="targetPoint"/>
<mxPoint x="359" y="550" as="sourcePoint"/> <mxPoint x="359" y="550" as="sourcePoint"/>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="46" value="撤销申请开票" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="45"> <mxCell id="46" value="拒绝开票" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="45" vertex="1" connectable="0">
<mxGeometry x="-0.2606" relative="1" as="geometry"> <mxGeometry x="-0.2606" relative="1" as="geometry">
<mxPoint x="6" as="offset"/> <mxPoint x="6" as="offset"/>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="49" value="" style="edgeStyle=orthogonalEdgeStyle;html=1;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="8" target="13"> <mxCell id="49" value="" style="edgeStyle=orthogonalEdgeStyle;html=1;verticalAlign=bottom;endArrow=open;endSize=8;strokeColor=#ff0000;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="8" target="13" edge="1">
<mxGeometry relative="1" as="geometry"> <mxGeometry relative="1" as="geometry">
<mxPoint x="413" y="500" as="targetPoint"/> <mxPoint x="413" y="500" as="targetPoint"/>
<mxPoint x="413" y="420" as="sourcePoint"/> <mxPoint x="413" y="420" as="sourcePoint"/>
</mxGeometry> </mxGeometry>
</mxCell> </mxCell>
<mxCell id="50" value="不支持开发票" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" vertex="1" connectable="0" parent="49"> <mxCell id="50" value="不支持开发票" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="49" vertex="1" connectable="0">
<mxGeometry x="-0.2513" y="-1" relative="1" as="geometry"> <mxGeometry x="-0.2513" y="-1" relative="1" as="geometry">
<mxPoint x="1" y="6" as="offset"/> <mxPoint x="1" y="6" as="offset"/>
</mxGeometry> </mxGeometry>

View File

@ -0,0 +1,260 @@
<mxfile host="65bd71144e">
<diagram id="PzGHVj2JrUCharDApkJk" name="第 1 页">
<mxGraphModel dx="1496" dy="1393" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="7" value="" style="edgeStyle=none;html=1;" parent="1" source="5" target="6" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="5" value="调用登录&lt;br&gt;发送验证码&lt;br&gt;接口" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.start_1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="59" y="60" width="100" height="60" as="geometry"/>
</mxCell>
<mxCell id="9" value="" style="edgeStyle=none;html=1;" parent="1" source="6" target="8" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="13" value="不存在账户" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="9" vertex="1" connectable="0">
<mxGeometry x="-0.325" y="-1" relative="1" as="geometry">
<mxPoint x="13" y="-1" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="11" value="" style="edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="6" target="10" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="12" value="存在账户" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="11" vertex="1" connectable="0">
<mxGeometry x="0.2667" y="-1" relative="1" as="geometry">
<mxPoint x="1" y="-14" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="6" value="是否存在账户" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="59" y="170" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="18" value="" style="edgeStyle=none;html=1;" parent="1" source="8" target="17" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="22" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="18" vertex="1" connectable="0">
<mxGeometry x="-0.3667" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="20" value="" style="edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="8" target="10" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="309" y="340" as="targetPoint"/>
<Array as="points">
<mxPoint x="289" y="388"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="21" value="是" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="20" vertex="1" connectable="0">
<mxGeometry x="-0.2857" y="-1" relative="1" as="geometry">
<mxPoint x="1" y="-41" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="8" value="是否开启&lt;br&gt;自动注册" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="239" y="170" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="24" value="" style="edgeStyle=none;html=1;" parent="1" source="10" target="23" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="10" value="发送&lt;br&gt;登录验证码" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="59" y="338" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="17" value="抛出异常&lt;br&gt;没有该用户" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="379" y="190" width="100" height="60" as="geometry"/>
</mxCell>
<mxCell id="34" value="" style="edgeStyle=none;html=1;" parent="1" source="23" target="33" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="23" value="用户收到验证码&lt;br&gt;携带验证码调用&lt;br&gt;登录验证接口" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="59" y="490" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="30" value="" style="edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="27" target="29" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="109" y="1027"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="32" value="是" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="30" vertex="1" connectable="0">
<mxGeometry x="-0.22" y="-2" relative="1" as="geometry">
<mxPoint x="2" y="-25" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="40" value="" style="edgeStyle=none;html=1;" parent="1" source="27" target="31" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="41" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="40" vertex="1" connectable="0">
<mxGeometry x="-0.3619" y="-4" relative="1" as="geometry">
<mxPoint y="-4" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="27" value="是否存在账户" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="59" y="866.75" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="29" value="返回token" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="189" y="996.75" width="100" height="60" as="geometry"/>
</mxCell>
<mxCell id="42" style="edgeStyle=none;html=1;" parent="1" source="31" target="29" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="379" y="1027"/>
</Array>
</mxGeometry>
</mxCell>
<mxCell id="31" value="创建账户" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="329" y="866.75" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="36" value="" style="edgeStyle=none;html=1;" parent="1" source="33" target="35" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="39" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="36" vertex="1" connectable="0">
<mxGeometry x="-0.3619" y="-1" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="37" value="" style="edgeStyle=none;html=1;" parent="1" source="33" target="27" edge="1">
<mxGeometry relative="1" as="geometry">
<Array as="points"/>
</mxGeometry>
</mxCell>
<mxCell id="38" value="是" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="37" vertex="1" connectable="0">
<mxGeometry x="-0.1238" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="33" value="验证码&lt;br&gt;是否正确" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="59" y="728" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="35" value="抛出异常&lt;br&gt;验证码错误" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="379" y="748" width="100" height="60" as="geometry"/>
</mxCell>
<mxCell id="45" value="" style="edgeStyle=none;html=1;" parent="1" source="43" target="44" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="43" value="调用注册&lt;br&gt;发送验证码&lt;br&gt;接口" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.start_1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="669" y="348" width="100" height="60" as="geometry"/>
</mxCell>
<mxCell id="48" value="" style="edgeStyle=none;html=1;" parent="1" source="44" target="47" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="49" value="是" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="48" vertex="1" connectable="0">
<mxGeometry x="-0.4111" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="51" value="" style="edgeStyle=none;html=1;" parent="1" source="44" target="50" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="52" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="51" vertex="1" connectable="0">
<mxGeometry x="-0.5067" y="1" relative="1" as="geometry">
<mxPoint x="-1" y="10" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="44" value="是否存在账户" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="669" y="448" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="47" value="抛出异常&lt;br&gt;账户已存在" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="509" y="468" width="100" height="60" as="geometry"/>
</mxCell>
<mxCell id="54" value="" style="edgeStyle=none;html=1;" parent="1" source="50" target="53" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="50" value="发送&lt;br&gt;注册验证码" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="669" y="578" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="56" value="" style="edgeStyle=none;html=1;" parent="1" source="53" target="55" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="53" value="用户收到验证码&lt;br&gt;携带验证码调用&lt;br&gt;注册验证接口" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="669" y="728" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="60" style="edgeStyle=none;html=1;" parent="1" source="55" target="35" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="61" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="60" vertex="1" connectable="0">
<mxGeometry x="0.2444" y="5" relative="1" as="geometry">
<mxPoint x="11" y="-5" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="62" style="edgeStyle=none;html=1;" parent="1" source="55" target="81" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="709" y="873" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="63" value="是" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="62" vertex="1" connectable="0">
<mxGeometry x="-0.2358" y="4" relative="1" as="geometry">
<mxPoint x="-4" y="-7" as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="55" value="验证码&lt;br&gt;是否正确" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="529" y="728" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="70" value="" style="edgeStyle=none;html=1;" parent="1" source="64" target="69" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="64" value="调用重置密码&lt;br&gt;发送验证码&lt;br&gt;接口" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.start_1;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="516.5" y="60" width="100" height="60" as="geometry"/>
</mxCell>
<mxCell id="72" value="" style="edgeStyle=none;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="69" target="17" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="859" y="193" as="targetPoint"/>
</mxGeometry>
</mxCell>
<mxCell id="73" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="72" vertex="1" connectable="0">
<mxGeometry x="-0.2519" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="75" value="" style="edgeStyle=none;html=1;" parent="1" source="69" target="74" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="69" value="是否存在账户" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="516.5" y="170" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="77" value="" style="edgeStyle=none;html=1;" parent="1" source="74" target="76" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="74" value="发送&lt;br&gt;重置验证码" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="516.5" y="338" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="79" value="" style="edgeStyle=none;html=1;" parent="1" source="76" target="78" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="76" value="用户收到验证码&lt;br&gt;携带验证码调用&lt;br&gt;重置验证接口" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="379" y="338" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="82" style="edgeStyle=none;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;exitPerimeter=0;" parent="1" source="78" target="35" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="83" value="否" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="82" vertex="1" connectable="0">
<mxGeometry x="-0.35" y="1" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="85" value="" style="edgeStyle=none;html=1;" parent="1" source="78" target="84" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="86" value="是" style="edgeLabel;html=1;align=center;verticalAlign=middle;resizable=0;points=[];" parent="85" vertex="1" connectable="0">
<mxGeometry x="-0.3905" relative="1" as="geometry">
<mxPoint as="offset"/>
</mxGeometry>
</mxCell>
<mxCell id="78" value="验证码&lt;br&gt;是否正确" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.decision;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="379" y="518" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="81" value="创建账户" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="529" y="874.75" width="100" height="60" as="geometry"/>
</mxCell>
<mxCell id="88" value="" style="edgeStyle=none;html=1;" parent="1" source="84" target="87" edge="1">
<mxGeometry relative="1" as="geometry"/>
</mxCell>
<mxCell id="84" value="修改原有的密码" style="rounded=1;whiteSpace=wrap;html=1;absoluteArcSize=1;arcSize=14;strokeWidth=2;" parent="1" vertex="1">
<mxGeometry x="239" y="518" width="100" height="100" as="geometry"/>
</mxCell>
<mxCell id="87" value="删除当前&lt;br&gt;登录用户&lt;br&gt;凭证信息" style="strokeWidth=2;html=1;shape=mxgraph.flowchart.terminator;whiteSpace=wrap;" parent="1" vertex="1">
<mxGeometry x="239" y="668" width="100" height="60" as="geometry"/>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@ -251,7 +251,7 @@
<!-- 集成第三方登录启动器 --> <!-- 集成第三方登录启动器 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-starter</artifactId> <artifactId>ruoyi-auth-starter</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
@ -290,7 +290,7 @@
<module>ruoyi-framework</module> <module>ruoyi-framework</module>
<module>ruoyi-system</module> <module>ruoyi-system</module>
<module>ruoyi-common</module> <module>ruoyi-common</module>
<module>ruoyi-oauth</module> <module>ruoyi-auth</module>
<module>ruoyi-pay</module> <module>ruoyi-pay</module>
<module>ruoyi-middleware</module> <module>ruoyi-middleware</module>
<module>ruoyi-plugins</module> <module>ruoyi-plugins</module>

View File

@ -38,7 +38,7 @@
<!-- 集成第三方登录启动器 --> <!-- 集成第三方登录启动器 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-starter</artifactId> <artifactId>ruoyi-auth-starter</artifactId>
</dependency> </dependency>
<!-- 集成第三方支付启动器 --> <!-- 集成第三方支付启动器 -->

View File

@ -42,6 +42,8 @@ public class CacheController
caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息")); caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "配置信息"));
caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "数据字典")); caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "数据字典"));
caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码")); caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码"));
caches.add(new SysCache(CacheConstants.PHONE_CODES, "短信验证码"));
caches.add(new SysCache(CacheConstants.EMAIL_CODES, "邮箱验证码"));
caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交")); caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交"));
caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理")); caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理"));
caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数")); caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数"));

View File

@ -1,5 +1,5 @@
# 请输入自己的appid和appsecret # 请输入自己的appid和appsecret
oauth: oauth:
wx: wx:
miniapp: miniapp:
open: true open: true
@ -12,15 +12,18 @@ oauth:
appSecret: appSecret appSecret: appSecret
url: https://api.weixin.qq.com/sns/oauth2/access_token url: https://api.weixin.qq.com/sns/oauth2/access_token
tfa:
phone: phone:
dysms: dysms:
# 阿里云短信 AccessKey ID
appId: appId appId: appId
# 阿里云短信 AccessKey Secret
appSecret: appSecret appSecret: appSecret
spring: spring:
mail: mail:
host: smtp.qq.com host: smtp.qq.com
# 邮箱地址 # 邮箱地址
username: username username: email
# 授权码 # 授权码
password: password password: password

View File

@ -65,7 +65,7 @@ spring:
# 国际化资源文件路径 # 国际化资源文件路径
basename: i18n/messages basename: i18n/messages
profiles: profiles:
active: druid,mybatis,oauth,pay,middleware active: druid,mybatis,auth,pay,middleware
# 文件上传 # 文件上传
servlet: servlet:
multipart: multipart:

View File

@ -8,7 +8,7 @@
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-oauth</artifactId> <artifactId>ruoyi-auth</artifactId>
<properties> <properties>
<justauth.version>1.16.6</justauth.version> <justauth.version>1.16.6</justauth.version>
@ -24,7 +24,7 @@
<!-- 第三方认证通用工具--> <!-- 第三方认证通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-common</artifactId> <artifactId>ruoyi-auth-common</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
@ -66,21 +66,21 @@
<!-- 手机号认证 --> <!-- 手机号认证 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-phone</artifactId> <artifactId>ruoyi-tfa-phone</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 邮箱认证 --> <!-- 邮箱认证 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-email</artifactId> <artifactId>ruoyi-tfa-email</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 第三方登录启动器 --> <!-- 第三方登录启动器 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-starter</artifactId> <artifactId>ruoyi-auth-starter</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
@ -88,12 +88,12 @@
<modules> <modules>
<module>ruoyi-oauth-common</module> <module>ruoyi-auth-common</module>
<module>ruoyi-oauth-justauth</module> <module>ruoyi-oauth-justauth</module>
<module>ruoyi-oauth-wx</module> <module>ruoyi-oauth-wx</module>
<module>ruoyi-oauth-phone</module> <module>ruoyi-tfa-phone</module>
<module>ruoyi-oauth-email</module> <module>ruoyi-tfa-email</module>
<module>ruoyi-oauth-starter</module> <module>ruoyi-auth-starter</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>
</project> </project>

View File

@ -2,13 +2,13 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" <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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<artifactId>ruoyi-oauth</artifactId> <artifactId>ruoyi-auth</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.7.3.4</version> <version>3.8.7.3.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-oauth-common</artifactId> <artifactId>ruoyi-auth-common</artifactId>
<description> <description>
system系统模块 system系统模块

View File

@ -1,4 +1,4 @@
package com.ruoyi.oauth.common.controller; package com.ruoyi.auth.common.controller;
import java.util.List; import java.util.List;
@ -13,14 +13,14 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.auth.common.domain.OauthUser;
import com.ruoyi.auth.common.service.IOauthUserService;
import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.oauth.common.domain.OauthUser;
import com.ruoyi.oauth.common.service.IOauthUserService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;

View File

@ -1,4 +1,4 @@
package com.ruoyi.oauth.common.domain; package com.ruoyi.auth.common.domain;
import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; import org.apache.commons.lang3.builder.ToStringStyle;

View File

@ -0,0 +1,53 @@
package com.ruoyi.auth.common.enums;
public enum OauthVerificationUse {
LOGIN("登录", "login"),
REGISTER("注册", "register"),
DISABLE("禁用", "disable"),
RESET("重置", "reset"),
BIND("绑定", "bind"),
OTHER("其他", "other");
private String name;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public static OauthVerificationUse getByValue(String value) {
for (OauthVerificationUse use : OauthVerificationUse.values()) {
if (use.getValue().equals(value)) {
return use;
}
}
return null;
}
public static OauthVerificationUse getByName(String name) {
for (OauthVerificationUse use : OauthVerificationUse.values()) {
if (use.getName().equals(name)) {
return use;
}
}
return null;
}
private OauthVerificationUse(String name, String value) {
this.name = name;
this.value = value;
}
}

View File

@ -1,10 +1,10 @@
package com.ruoyi.oauth.common.mapper; package com.ruoyi.auth.common.mapper;
import java.util.List; import java.util.List;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import com.ruoyi.oauth.common.domain.OauthUser; import com.ruoyi.auth.common.domain.OauthUser;
/** /**
* 第三方认证Mapper接口 * 第三方认证Mapper接口

View File

@ -1,9 +1,9 @@
package com.ruoyi.oauth.common.service; package com.ruoyi.auth.common.service;
import java.util.List; import java.util.List;
import com.ruoyi.auth.common.domain.OauthUser;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.oauth.common.domain.OauthUser;
/** /**
* 第三方认证Service接口 * 第三方认证Service接口

View File

@ -1,6 +1,6 @@
package com.ruoyi.oauth.common.service; package com.ruoyi.auth.common.service;
import com.ruoyi.oauth.common.enums.OauthVerificationUse; import com.ruoyi.auth.common.enums.OauthVerificationUse;
/** /**
* code认证方式接口 * code认证方式接口
@ -10,6 +10,6 @@ import com.ruoyi.oauth.common.enums.OauthVerificationUse;
*/ */
public interface OauthVerificationCodeService { public interface OauthVerificationCodeService {
public boolean sendCode(String o, String code,OauthVerificationUse use) throws Exception; public boolean sendCode(String o, String code,OauthVerificationUse use) throws Exception;
public String checkCode(String o, String code,OauthVerificationUse use) throws Exception; public boolean checkCode(String o, String code,OauthVerificationUse use) throws Exception;
} }

View File

@ -1,14 +1,14 @@
package com.ruoyi.oauth.common.service.impl; package com.ruoyi.auth.common.service.impl;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ruoyi.auth.common.domain.OauthUser;
import com.ruoyi.auth.common.mapper.OauthUserMapper;
import com.ruoyi.auth.common.service.IOauthUserService;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.oauth.common.domain.OauthUser;
import com.ruoyi.oauth.common.mapper.OauthUserMapper;
import com.ruoyi.oauth.common.service.IOauthUserService;
import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.mapper.SysUserMapper;
/** /**

View File

@ -0,0 +1,28 @@
package com.ruoyi.auth.common.utils;
import java.util.Random;
public class RandomCodeUtil {
public static String randomString(String characters, int length) {
StringBuilder result = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
int index = random.nextInt(characters.length());
result.append(characters.charAt(index));
}
return result.toString();
}
public static String numberCode(int length) {
String characters = "0123456789";
return randomString(characters, length);
}
public static String code(int length) {
String characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
return randomString(characters, length);
}
}

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper <!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.oauth.common.mapper.OauthUserMapper"> <mapper namespace="com.ruoyi.auth.common.mapper.OauthUserMapper">
<resultMap type="OauthUser" id="OauthUserResult"> <resultMap type="OauthUser" id="OauthUserResult">
<result property="id" column="id" /> <result property="id" column="id" />

View File

@ -3,13 +3,13 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<artifactId>ruoyi-oauth</artifactId> <artifactId>ruoyi-auth</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.7.3.4</version> <version>3.8.7.3.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-oauth-starter</artifactId> <artifactId>ruoyi-auth-starter</artifactId>
<description> <description>
第三方认证模块 第三方认证模块
@ -19,7 +19,7 @@
<!-- 第三方认证通用工具--> <!-- 第三方认证通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-common</artifactId> <artifactId>ruoyi-auth-common</artifactId>
</dependency> </dependency>
<!-- justauth通用认证 --> <!-- justauth通用认证 -->
@ -37,13 +37,13 @@
<!-- 手机号认证 --> <!-- 手机号认证 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-phone</artifactId> <artifactId>ruoyi-tfa-phone</artifactId>
</dependency> </dependency>
<!-- 邮箱认证 --> <!-- 邮箱认证 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-email</artifactId> <artifactId>ruoyi-tfa-email</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" <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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<artifactId>ruoyi-oauth</artifactId> <artifactId>ruoyi-auth</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.7.3.4</version> <version>3.8.7.3.4</version>
</parent> </parent>
@ -19,7 +19,7 @@
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-common</artifactId> <artifactId>ruoyi-auth-common</artifactId>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -25,8 +25,8 @@ import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysPermissionService; import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.oauth.common.domain.OauthUser; import com.ruoyi.auth.common.domain.OauthUser;
import com.ruoyi.oauth.common.service.IOauthUserService; import com.ruoyi.auth.common.service.IOauthUserService;
import com.ruoyi.oauth.justauth.utils.AuthUtils; import com.ruoyi.oauth.justauth.utils.AuthUtils;
import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.ISysUserService;

View File

@ -3,7 +3,7 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<artifactId>ruoyi-oauth</artifactId> <artifactId>ruoyi-auth</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.7.3.4</version> <version>3.8.7.3.4</version>
</parent> </parent>
@ -20,7 +20,7 @@
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-common</artifactId> <artifactId>ruoyi-auth-common</artifactId>
</dependency> </dependency>

View File

@ -11,8 +11,8 @@ import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.oauth.common.domain.OauthUser; import com.ruoyi.auth.common.domain.OauthUser;
import com.ruoyi.oauth.common.service.IOauthUserService; import com.ruoyi.auth.common.service.IOauthUserService;
import com.ruoyi.oauth.wx.constant.WxMiniAppConstant; import com.ruoyi.oauth.wx.constant.WxMiniAppConstant;
import com.ruoyi.oauth.wx.constant.WxPubConstant; import com.ruoyi.oauth.wx.constant.WxPubConstant;
import com.ruoyi.oauth.wx.service.Impl.WxLoginServiceImpl; import com.ruoyi.oauth.wx.service.Impl.WxLoginServiceImpl;

View File

@ -12,11 +12,11 @@ import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpClientUtil;
import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.framework.web.service.UserDetailsServiceImpl; import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
import com.ruoyi.oauth.common.domain.OauthUser; import com.ruoyi.auth.common.domain.OauthUser;
import com.ruoyi.oauth.common.service.IOauthUserService; import com.ruoyi.auth.common.service.IOauthUserService;
import com.ruoyi.oauth.common.utils.HttpClientUtil;
import com.ruoyi.oauth.wx.constant.WxMiniAppConstant; import com.ruoyi.oauth.wx.constant.WxMiniAppConstant;
import com.ruoyi.oauth.wx.constant.WxPubConstant; import com.ruoyi.oauth.wx.constant.WxPubConstant;
import com.ruoyi.oauth.wx.service.WxLoginService; import com.ruoyi.oauth.wx.service.WxLoginService;
@ -29,9 +29,6 @@ public class WxLoginServiceImpl implements WxLoginService {
@Autowired @Autowired
private WxPubConstant wxH5Constant; private WxPubConstant wxH5Constant;
@Autowired
private HttpClientUtil httpClientUtil;
@Autowired @Autowired
private TokenService tokenService; private TokenService tokenService;
@Autowired @Autowired
@ -44,7 +41,7 @@ public class WxLoginServiceImpl implements WxLoginService {
public Map<String, String> doAuth(String url, String appid, String secret, String code) { public Map<String, String> doAuth(String url, String appid, String secret, String code) {
String getMessageUrl = url + "?appid=" + appid + "&secret=" + secret + "&js_code=" + code String getMessageUrl = url + "?appid=" + appid + "&secret=" + secret + "&js_code=" + code
+ "&grant_type=authorization_code"; + "&grant_type=authorization_code";
String result = httpClientUtil.sendHttpGet(getMessageUrl); String result = HttpClientUtil.sendHttpGet(getMessageUrl);
JSONObject jsonObject = JSON.parseObject(result); JSONObject jsonObject = JSON.parseObject(result);
if (jsonObject.containsKey("openid")) { if (jsonObject.containsKey("openid")) {
String openid = jsonObject.getString("openid"); String openid = jsonObject.getString("openid");

View File

@ -1,6 +1,6 @@
package com.ruoyi.oauth.wx.service; package com.ruoyi.oauth.wx.service;
import com.ruoyi.oauth.common.domain.OauthUser; import com.ruoyi.auth.common.domain.OauthUser;
public interface WxLoginService { public interface WxLoginService {
public String doLoginMiniApp(String code); public String doLoginMiniApp(String code);

View File

@ -2,13 +2,13 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" <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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<artifactId>ruoyi-oauth</artifactId> <artifactId>ruoyi-auth</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.7.3.4</version> <version>3.8.7.3.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-oauth-email</artifactId> <artifactId>ruoyi-tfa-email</artifactId>
<description> <description>
邮箱认证模块 邮箱认证模块
@ -19,7 +19,7 @@
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-common</artifactId> <artifactId>ruoyi-auth-common</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -0,0 +1,18 @@
package com.ruoyi.tfa.email.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Configuration
public class EmailConfig {
@Value("${spring.mail.username}")
private String from;
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
}

View File

@ -0,0 +1,32 @@
package com.ruoyi.tfa.email.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.tfa.email.service.impl.MailServiceImpl;
@RestController
@RequestMapping("/auth/mail")
public class MailAuthController extends BaseController {
@Autowired
MailServiceImpl serviceImpl;
@PostMapping("/send/bind") // 发送验证码
public AjaxResult send(@RequestBody LoginBody loginBody) {
serviceImpl.doBind(loginBody);
return success();
}
@PostMapping("/verify/bind") // 发送验证码
public AjaxResult verify(@RequestBody LoginBody loginBody) {
serviceImpl.doBindVerify(loginBody);
return success();
}
}

View File

@ -0,0 +1,6 @@
package com.ruoyi.tfa.email.service;
import com.ruoyi.auth.common.service.OauthVerificationCodeService;
public interface IMailService extends OauthVerificationCodeService {
}

View File

@ -0,0 +1,156 @@
package com.ruoyi.tfa.email.service.impl;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.auth.common.enums.OauthVerificationUse;
import com.ruoyi.auth.common.utils.RandomCodeUtil;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.tfa.email.service.IMailService;
import com.ruoyi.tfa.email.utils.EmailUtil;
@Service
public class MailServiceImpl implements IMailService {
@Autowired
private ISysUserService userService;
@Autowired
private TokenService tokenService;
@Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
private static final Logger log = LoggerFactory.getLogger(MailServiceImpl.class);
@Override
public boolean sendCode(String email, String code, OauthVerificationUse use) {
if (CacheUtils.hasKey(CacheConstants.EMAIL_CODES, use.getValue() + email)) {
throw new ServiceException("当前验证码未失效请在1分钟后再发送短信");
}
try {
EmailUtil.sendMessage(email, "验证码邮件", "您收到的验证码是:" + code);
CacheUtils.put(CacheConstants.EMAIL_CODES, use.getValue() + email, code, 10, TimeUnit.MINUTES);
log.info("发送邮箱验证码成功:{ email: " + email + " code:" + code + "}");
return true;
} catch (Exception e) {
throw new ServiceException("发送手机验证码异常:" + email);
}
}
@Override
public boolean checkCode(String email, String code, OauthVerificationUse use) {
if (StringUtils.isEmpty(code))
return false;
String cachedCode = CacheUtils.get(CacheConstants.EMAIL_CODES, use.getValue() + email, String.class); // 从缓存中获取验证码
CacheUtils.remove(CacheConstants.EMAIL_CODES, use.getValue() + email);
return code.equals(cachedCode);
}
public void doLogin(LoginBody loginBody, boolean isRegister) {
SysUser sysUser = userService.selectUserByEmail(loginBody.getEmail());
if (sysUser == null && !isRegister) {
throw new ServiceException("该邮箱未绑定用户");
} else {
sendCode(loginBody.getEmail(), RandomCodeUtil.numberCode(6), OauthVerificationUse.LOGIN);
}
}
public String doLoginVerify(LoginBody loginBody, boolean isRegister) {
if (checkCode(loginBody.getEmail(), loginBody.getCode(), OauthVerificationUse.LOGIN)) {
SysUser sysUser = userService.selectUserByEmail(loginBody.getEmail());
if (sysUser == null) {
if (isRegister) {
sysUser = new SysUser();
sysUser.setUserName(loginBody.getEmail());
sysUser.setPassword(SecurityUtils.encryptPassword(RandomCodeUtil.code(16)));
sysUser.setEmail(loginBody.getEmail());
} else {
throw new ServiceException("该邮箱未绑定用户");
}
}
LoginUser loginUser = (LoginUser) userDetailsServiceImpl.createLoginUser(sysUser);
return tokenService.createToken(loginUser);
} else {
throw new ServiceException("验证码错误");
}
}
public void doRegister(RegisterBody registerBody) {
SysUser sysUser = userService.selectUserByEmail(registerBody.getEmail());
if (sysUser != null) {
throw new ServiceException("该邮箱已绑定用户");
} else {
sendCode(registerBody.getEmail(), RandomCodeUtil.numberCode(6), OauthVerificationUse.REGISTER);
}
}
public void doRegisterVerify(RegisterBody registerBody) {
if (checkCode(registerBody.getEmail(), registerBody.getCode(), OauthVerificationUse.REGISTER)) {
SysUser sysUser = new SysUser();
sysUser.setUserName(registerBody.getEmail());
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
sysUser.setEmail(registerBody.getEmail());
} else {
throw new ServiceException("验证码错误");
}
}
public void doReset(String email) {
SysUser sysUser = userService.selectUserByEmail(email);
if (sysUser == null) {
throw new ServiceException("该邮箱未绑定用户");
} else {
sendCode(email, RandomCodeUtil.numberCode(6), OauthVerificationUse.RESET);
}
}
public int doResetVerify(RegisterBody registerBody) {
if (checkCode(registerBody.getEmail(), registerBody.getCode(), OauthVerificationUse.RESET)) {
SysUser sysUser = userService.selectUserById(SecurityUtils.getUserId());
sysUser.setEmail(registerBody.getEmail());
return userService.updateUser(sysUser);
} else {
throw new ServiceException("验证码错误");
}
}
public void doBind(LoginBody loginBody) {
SysUser sysUser = userService.selectUserByEmail(loginBody.getEmail());
if (sysUser != null) {
throw new ServiceException("该邮箱已绑定用户");
}
sysUser = userService.selectUserById(SecurityUtils.getUserId());
if (!SecurityUtils.matchesPassword(loginBody.getPassword(), sysUser.getPassword())) {
throw new ServiceException("密码错误");
}
sendCode(loginBody.getEmail(), RandomCodeUtil.numberCode(6), OauthVerificationUse.BIND);
}
public void doBindVerify(LoginBody loginBody) {
if (checkCode(loginBody.getEmail(), loginBody.getCode(), OauthVerificationUse.BIND)) {
SysUser sysUser = userService.selectUserById(SecurityUtils.getUserId());
if (!SecurityUtils.matchesPassword(loginBody.getPassword(), sysUser.getPassword())) {
throw new ServiceException("密码错误");
}
sysUser.setEmail(loginBody.getEmail());
userService.updateUser(sysUser);
} else {
throw new ServiceException("验证码错误");
}
}
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.tfa.email.utils;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.tfa.email.config.EmailConfig;
public class EmailUtil {
public static void sendMessage(String email, String title, String message) {
EmailConfig emailConfig = SpringUtils.getBean(EmailConfig.class);
JavaMailSenderImpl mailSender = SpringUtils.getBean(JavaMailSenderImpl.class);
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setSubject(title);
simpleMailMessage.setText(message);
simpleMailMessage.setFrom(emailConfig.getFrom());
simpleMailMessage.setTo(email);
mailSender.send(simpleMailMessage);
}
}

View File

@ -3,13 +3,13 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent> <parent>
<artifactId>ruoyi-oauth</artifactId> <artifactId>ruoyi-auth</artifactId>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<version>3.8.7.3.4</version> <version>3.8.7.3.4</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>ruoyi-oauth-phone</artifactId> <artifactId>ruoyi-tfa-phone</artifactId>
<description> <description>
手机号认证模块 手机号认证模块
@ -20,7 +20,7 @@
<!-- 通用工具--> <!-- 通用工具-->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-oauth-common</artifactId> <artifactId>ruoyi-auth-common</artifactId>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -1,7 +1,7 @@
package com.ruoyi.oauth.phone.constant; package com.ruoyi.tfa.phone.constant;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.context.annotation.Configuration;
/** /**
* 手机号认证数据 * 手机号认证数据
@ -9,11 +9,11 @@ import org.springframework.stereotype.Component;
* @author Dftre * @author Dftre
* @date 2024-04-16 * @date 2024-04-16
*/ */
@Component @Configuration
public class DySmsConstant { public class DySmsConfig {
@Value("${oauth.phone.dysms.appId}") @Value("${tfa.phone.dysms.appId}")
private String accessKeyId; private String accessKeyId;
@Value("${oauth.phone.dysms.appSecret}") @Value("${tfa.phone.dysms.appSecret}")
private String accessKeySecret; private String accessKeySecret;
public String getAccessKeyId() { public String getAccessKeyId() {

View File

@ -0,0 +1,37 @@
package com.ruoyi.tfa.phone.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.tfa.phone.service.Impl.DySmsServiceImpl;
/**
* 手机号认证Controller
*
* @author zlh
* @date 2024-04-16
*/
@RestController
@RequestMapping("/tfa/phone")
public class DySmsAuthController extends BaseController {
@Autowired
public DySmsServiceImpl dySmsService;
@PostMapping("/send/bind") // 发送验证码
public AjaxResult send(@RequestBody LoginBody loginBody) {
dySmsService.doBind(loginBody);
return success();
}
@PostMapping("/verify/bind") // 发送验证码
public AjaxResult verify(@RequestBody LoginBody loginBody) {
dySmsService.doBindVerify(loginBody);
return success();
}
}

View File

@ -1,4 +1,4 @@
package com.ruoyi.oauth.phone.enums; package com.ruoyi.tfa.phone.enums;
import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.StringUtils;

View File

@ -0,0 +1,13 @@
package com.ruoyi.tfa.phone.service;
import com.ruoyi.auth.common.service.OauthVerificationCodeService;
/**
* 手机号认证Servcie
*
* @author zlh
* @date 2024-04-16
*/
public interface DySmsService extends OauthVerificationCodeService {
}

View File

@ -0,0 +1,166 @@
package com.ruoyi.tfa.phone.service.Impl;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.auth.common.enums.OauthVerificationUse;
import com.ruoyi.auth.common.utils.RandomCodeUtil;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.domain.model.RegisterBody;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.tfa.phone.enums.DySmsTemplate;
import com.ruoyi.tfa.phone.service.DySmsService;
import com.ruoyi.tfa.phone.utils.DySmsUtil;
/**
* 手机号认证Servcie
*
* @author zlh
* @date 2024-04-16
*/
@Service
public class DySmsServiceImpl implements DySmsService {
@Autowired
private ISysUserService userService;
@Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
@Autowired
private TokenService tokenService;
private static final Logger log = LoggerFactory.getLogger(DySmsServiceImpl.class);
@Override
public boolean sendCode(String phone, String code, OauthVerificationUse use) {
if (CacheUtils.hasKey(CacheConstants.PHONE_CODES, use.getValue() + phone)) {
throw new ServiceException("当前验证码未失效请在1分钟后再发送短信");
}
try {
JSONObject templateParams = new JSONObject();
templateParams.put("code", code);
DySmsUtil.sendSms(DySmsTemplate.Test_TEMPLATE_CODE, templateParams, phone);
CacheUtils.put(CacheConstants.PHONE_CODES, use.getValue() + phone, code, 1, TimeUnit.MINUTES);
log.info("发送手机验证码成功:{ phone: " + phone + " code:" + code + "}");
return true;
} catch (Exception e) {
throw new ServiceException("发送手机验证码异常:" + phone);
}
}
@Override
public boolean checkCode(String phone, String code, OauthVerificationUse use) {
if (StringUtils.isEmpty(code))
return false;
String cachedCode = CacheUtils.get(CacheConstants.PHONE_CODES, use.getValue() + phone, String.class); // 从缓存中获取验证码
CacheUtils.remove(CacheConstants.PHONE_CODES, use.getValue() + phone);
return code.equals(cachedCode);
}
public void doLogin(LoginBody loginBody, boolean isRegister) {
SysUser sysUser = userService.selectUserByPhone(loginBody.getPhonenumber());
if (sysUser == null && !isRegister) {
throw new ServiceException("该手机号未绑定用户");
} else {
sendCode(loginBody.getPhonenumber(), RandomCodeUtil.numberCode(6), OauthVerificationUse.LOGIN);
}
}
public String doLoginVerify(LoginBody loginBody, boolean isRegister) {
if (checkCode(loginBody.getPhonenumber(), loginBody.getCode(), OauthVerificationUse.LOGIN)) {
SysUser sysUser = userService.selectUserByPhone(loginBody.getPhonenumber());
if (sysUser == null) {
if (isRegister) {
sysUser = new SysUser();
sysUser.setUserName(loginBody.getPhonenumber());
sysUser.setPassword(SecurityUtils.encryptPassword(RandomCodeUtil.code(16)));
sysUser.setPhonenumber(loginBody.getPhonenumber());
} else {
throw new ServiceException("该手机号未绑定用户");
}
}
LoginUser loginUser = (LoginUser) userDetailsServiceImpl.createLoginUser(sysUser);
return tokenService.createToken(loginUser);
} else {
throw new ServiceException("验证码错误");
}
}
public void doRegister(RegisterBody registerBody) {
SysUser sysUser = userService.selectUserByPhone(registerBody.getPhonenumber());
if (sysUser != null) {
throw new ServiceException("该手机号已绑定用户");
} else {
sendCode(registerBody.getPhonenumber(), RandomCodeUtil.numberCode(6), OauthVerificationUse.REGISTER);
}
}
public void doRegisterVerify(RegisterBody registerBody) {
if (checkCode(registerBody.getPhonenumber(), registerBody.getCode(), OauthVerificationUse.REGISTER)) {
SysUser sysUser = new SysUser();
sysUser.setUserName(registerBody.getPhonenumber());
sysUser.setPassword(SecurityUtils.encryptPassword(registerBody.getPassword()));
sysUser.setPhonenumber(registerBody.getPhonenumber());
} else {
throw new ServiceException("验证码错误");
}
}
public void doReset(String phone) {
SysUser sysUser = userService.selectUserByPhone(phone);
if (sysUser == null) {
throw new ServiceException("该手机号未绑定用户");
} else {
sendCode(phone, RandomCodeUtil.numberCode(6), OauthVerificationUse.RESET);
}
}
public int doResetVerify(RegisterBody registerBody) {
if (checkCode(registerBody.getPhonenumber(), registerBody.getCode(), OauthVerificationUse.RESET)) {
SysUser sysUser = userService.selectUserById(SecurityUtils.getUserId());
sysUser.setPhonenumber(registerBody.getPhonenumber());
return userService.updateUser(sysUser);
} else {
throw new ServiceException("验证码错误");
}
}
public void doBind(LoginBody loginBody) {
SysUser sysUser = userService.selectUserByPhone(loginBody.getPhonenumber());
if (sysUser != null) {
throw new ServiceException("该手机号已绑定用户");
}
sysUser = userService.selectUserById(SecurityUtils.getUserId());
if (!SecurityUtils.matchesPassword(loginBody.getPassword(), sysUser.getPassword())) {
throw new ServiceException("密码错误");
}
sendCode(loginBody.getPhonenumber(), RandomCodeUtil.numberCode(6), OauthVerificationUse.BIND);
}
public void doBindVerify(LoginBody loginBody) {
if (checkCode(loginBody.getPhonenumber(), loginBody.getCode(), OauthVerificationUse.BIND)) {
SysUser sysUser = userService.selectUserById(SecurityUtils.getUserId());
if (!SecurityUtils.matchesPassword(loginBody.getPassword(), sysUser.getPassword())) {
throw new ServiceException("密码错误");
}
sysUser.setPhonenumber(loginBody.getPhonenumber());
userService.updateUser(sysUser);
} else {
throw new ServiceException("验证码错误");
}
}
}

View File

@ -1,9 +1,7 @@
package com.ruoyi.oauth.phone.utils; package com.ruoyi.tfa.phone.utils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dysmsapi20170525.Client; import com.aliyun.dysmsapi20170525.Client;
@ -13,15 +11,12 @@ import com.aliyun.tea.TeaException;
import com.aliyun.teaopenapi.models.Config; import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.Common; import com.aliyun.teautil.Common;
import com.aliyun.teautil.models.RuntimeOptions; import com.aliyun.teautil.models.RuntimeOptions;
import com.ruoyi.oauth.phone.constant.DySmsConstant; import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.oauth.phone.enums.DySmsTemplate; import com.ruoyi.tfa.phone.constant.DySmsConfig;
import com.ruoyi.tfa.phone.enums.DySmsTemplate;
@Component
public class DySmsUtil { public class DySmsUtil {
protected final Logger logger = LoggerFactory.getLogger(DySmsUtil.class); protected final static Logger logger = LoggerFactory.getLogger(DySmsUtil.class);
@Autowired
private DySmsConstant dySmsConfig;
/** /**
* 使用AK&SK初始化账号Client * 使用AK&SK初始化账号Client
@ -31,13 +26,13 @@ public class DySmsUtil {
* @return Client * @return Client
* @throws Exception * @throws Exception
*/ */
private Client createClient() throws Exception { private static Client createClient() throws Exception {
DySmsConfig dySmsConfig = SpringUtils.getBean(DySmsConfig.class);
Config config = new Config() Config config = new Config()
// 必填您的 AccessKey ID // 必填您的 AccessKey ID
.setAccessKeyId(dySmsConfig.getAccessKeyId()) .setAccessKeyId(dySmsConfig.getAccessKeyId())
// 必填您的 AccessKey Secret // 必填您的 AccessKey Secret
.setAccessKeySecret(dySmsConfig.getAccessKeySecret()); .setAccessKeySecret(dySmsConfig.getAccessKeySecret());
// Endpoint 请参考 https://api.aliyun.com/product/Dysmsapi
config.endpoint = "dysmsapi.aliyuncs.com"; config.endpoint = "dysmsapi.aliyuncs.com";
return new Client(config); return new Client(config);
} }
@ -49,7 +44,7 @@ public class DySmsUtil {
* @param dySmsTemplate * @param dySmsTemplate
* @throws Exception * @throws Exception
*/ */
private void validateParam(JSONObject templateParamJson, DySmsTemplate dySmsTemplate) { private static void validateParam(JSONObject templateParamJson, DySmsTemplate dySmsTemplate) {
String keys = dySmsTemplate.getKeys(); String keys = dySmsTemplate.getKeys();
String[] keyArr = keys.split(","); String[] keyArr = keys.split(",");
for (String item : keyArr) { for (String item : keyArr) {
@ -59,13 +54,8 @@ public class DySmsUtil {
} }
} }
public void sendSms(DySmsTemplate dySmsTemplate, JSONObject templateParamJson, String phone) public static void sendSms(DySmsTemplate dySmsTemplate, JSONObject templateParamJson, String phone)
throws Exception { throws Exception {
// 请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID
// ALIBABA_CLOUD_ACCESS_KEY_SECRET
// 工程代码泄露可能会导致 AccessKey 泄露并威胁账号下所有资源的安全性以下代码示例使用环境变量获取 AccessKey
// 的方式进行调用仅供参考建议使用更安全的 STS
// 方式更多鉴权访问方式请参见https://help.aliyun.com/document_detail/378657.html
validateParam(templateParamJson, dySmsTemplate); validateParam(templateParamJson, dySmsTemplate);
Client client = createClient(); Client client = createClient();
SendSmsRequest sendSmsRequest = new SendSmsRequest() SendSmsRequest sendSmsRequest = new SendSmsRequest()

View File

@ -5,8 +5,7 @@ package com.ruoyi.common.constant;
* *
* @author ruoyi * @author ruoyi
*/ */
public class CacheConstants public class CacheConstants {
{
/** /**
* 登录用户 redis key * 登录用户 redis key
*/ */
@ -41,4 +40,14 @@ public class CacheConstants
* 登录账户密码错误次数 redis key * 登录账户密码错误次数 redis key
*/ */
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt"; public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt";
/**
* 手机号验证码 phone codes
*/
public static final String PHONE_CODES = "phone_codes";
/**
* 邮箱验证码
*/
public static final String EMAIL_CODES = "email_codes";
} }

View File

@ -2,30 +2,49 @@ package com.ruoyi.common.core.domain.model;
import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
/** /**
* 用户登录对象 * 用户登录对象
* *
* @author ruoyi * @author ruoyi
*/ */
@Schema(title = "用户登录对象")
public class LoginBody extends BaseEntity { public class LoginBody extends BaseEntity {
/** /**
* 用户名 * 用户名
*/ */
@Schema(title = "用户名")
private String username; private String username;
/** /**
* 用户密码 * 用户密码
*/ */
@Schema(title = "用户密码")
private String password; private String password;
/**
* 手机号码
*/
@Schema(title = "手机号码")
private String phonenumber;
/**
* 邮箱
*/
@Schema(title = "邮箱")
private String email;
/** /**
* 验证码 * 验证码
*/ */
@Schema(title = "验证码")
private String code; private String code;
/** /**
* 唯一标识 * 唯一标识
*/ */
@Schema(title = "唯一标识")
private String uuid; private String uuid;
public String getUsername() { public String getUsername() {
@ -59,4 +78,20 @@ public class LoginBody extends BaseEntity {
public void setUuid(String uuid) { public void setUuid(String uuid) {
this.uuid = uuid; this.uuid = uuid;
} }
public String getPhonenumber() {
return phonenumber;
}
public void setPhonenumber(String phonenumber) {
this.phonenumber = phonenumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
} }

View File

@ -1,10 +1,13 @@
package com.ruoyi.common.core.domain.model; package com.ruoyi.common.core.domain.model;
import io.swagger.v3.oas.annotations.media.Schema;
/** /**
* 用户注册对象 * 用户注册对象
* *
* @author ruoyi * @author ruoyi
*/ */
@Schema(title = "用户注册对象")
public class RegisterBody extends LoginBody public class RegisterBody extends LoginBody
{ {

View File

@ -1,37 +0,0 @@
package com.ruoyi.oauth.common.enums;
public enum OauthVerificationUse {
LOGIN("登录", "login"),
REGISTER("注册", "register"),
DISABLE("禁用", "disable"),
RESET_PASSWORD("重置密码", "reset_password"),
RESET_PHONE("重置手机号", "reset_phone"),
Other("其他","other");
private String name;
private String value;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
private OauthVerificationUse(String name, String value) {
this.name = name;
this.value = value;
}
}

View File

@ -1,298 +0,0 @@
package com.ruoyi.oauth.common.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.util.PublicSuffixMatcher;
import org.apache.http.conn.util.PublicSuffixMatcherLoader;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
@Component
public class HttpClientUtil {
/**
* 默认参数设置
* setConnectTimeout设置连接超时时间单位毫秒
* setConnectionRequestTimeout设置从connect Manager获取Connection 超时时间单位毫秒
* setSocketTimeout请求获取数据的超时时间单位毫秒访问一个接口多少时间内无法返回数据就直接放弃此次调用 暂时定义15分钟
*/
private RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(600000).setConnectTimeout(600000).setConnectionRequestTimeout(600000).build();
/**
* 静态内部类---作用单例产生类的实例
*
* @author Administrator
*/
private static class LazyHolder {
private static final HttpClientUtil INSTANCE = new HttpClientUtil();
}
private HttpClientUtil() {
}
public static HttpClientUtil getInstance() {
return LazyHolder.INSTANCE;
}
/**
* 发送 post请求
*
* @param httpUrl 地址
*/
public String sendHttpPost(String httpUrl) {
HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
return sendHttpPost(httpPost);
}
/**
* 发送 post请求
*
* @param httpUrl 地址
* @param params 参数(格式:key1=value1&key2=value2)
*/
public String sendHttpPost(String httpUrl, String params) {
HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
try {
//设置参数
StringEntity stringEntity = new StringEntity(params, "UTF-8");
stringEntity.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(stringEntity);
} catch (Exception e) {
e.printStackTrace();
}
return sendHttpPost(httpPost);
}
/**
* 发送 post请求
*
* @param httpUrl 地址
* @param maps 参数
*/
public String sendHttpPost(String httpUrl, Map<String, String> maps) {
HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
// 创建参数队列
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
for (String key : maps.keySet()) {
nameValuePairs.add(new BasicNameValuePair(key, maps.get(key)));
}
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
return sendHttpPost(httpPost);
}
/**
* 发送Post请求
*
* @param httpPost
* @return
*/
private String sendHttpPost(HttpPost httpPost) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
HttpEntity entity = null;
String responseContent = null;
try {
// 创建默认的httpClient实例
httpClient = HttpClients.createDefault();
httpPost.setConfig(requestConfig);
// 执行请求
long execStart = System.currentTimeMillis();
response = httpClient.execute(httpPost);
long execEnd = System.currentTimeMillis();
System.out.println("=================执行post请求耗时" + (execEnd - execStart) + "ms");
long getStart = System.currentTimeMillis();
entity = response.getEntity();
responseContent = EntityUtils.toString(entity, "UTF-8");
long getEnd = System.currentTimeMillis();
System.out.println("=================获取响应结果耗时:" + (getEnd - getStart) + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭连接,释放资源
if (response != null) {
response.close();
}
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return responseContent;
}
/**
* 发送 get请求
*
* @param httpUrl
*/
public String sendHttpGet(String httpUrl) {
HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
return sendHttpGet(httpGet);
}
/**
* 发送 get请求Https
*
* @param httpUrl
*/
public String sendHttpsGet(String httpUrl) {
HttpGet httpGet = new HttpGet(httpUrl);// 创建get请求
return sendHttpsGet(httpGet);
}
/**
* 发送Get请求
*
* @param httpGet
* @return
*/
private String sendHttpGet(HttpGet httpGet) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
HttpEntity entity = null;
String responseContent = null;
try {
// 创建默认的httpClient实例.
httpClient = HttpClients.createDefault();
httpGet.setConfig(requestConfig);
// 执行请求
response = httpClient.execute(httpGet);
entity = response.getEntity();
responseContent = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭连接,释放资源
if (response != null) {
response.close();
}
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return responseContent;
}
/**
* 发送Get请求Https
*
* @param httpGet
* @return
*/
private String sendHttpsGet(HttpGet httpGet) {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
HttpEntity entity = null;
String responseContent = null;
try {
// 创建默认的httpClient实例.
PublicSuffixMatcher publicSuffixMatcher = PublicSuffixMatcherLoader.load(new URL(httpGet.getURI().toString()));
DefaultHostnameVerifier hostnameVerifier = new DefaultHostnameVerifier(publicSuffixMatcher);
httpClient = HttpClients.custom().setSSLHostnameVerifier(hostnameVerifier).build();
httpGet.setConfig(requestConfig);
// 执行请求
response = httpClient.execute(httpGet);
entity = response.getEntity();
responseContent = EntityUtils.toString(entity, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 关闭连接,释放资源
if (response != null) {
response.close();
}
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return responseContent;
}
/**
* 发送xml数据
*
* @param url
* @param xmlData
* @return
* @throws ClientProtocolException
* @throws IOException
*/
public static HttpResponse sendXMLDataByPost(String url, String xmlData)
throws ClientProtocolException, IOException {
HttpClient httpClient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(url);
StringEntity entity = new StringEntity(xmlData);
httppost.setEntity(entity);
httppost.setHeader("Content-Type", "text/xml;charset=UTF-8");
HttpResponse response = httpClient.execute(httppost);
return response;
}
/**
* 获得响应HTTP实体内容
*
* @param response
* @return
* @throws IOException
* @throws UnsupportedEncodingException
*/
public static String getHttpEntityContent(HttpResponse response) throws IOException, UnsupportedEncodingException {
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream is = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String line = br.readLine();
StringBuilder sb = new StringBuilder();
while (line != null) {
sb.append(line + "\n");
line = br.readLine();
}
return sb.toString();
}
return "";
}
}

View File

@ -1,19 +0,0 @@
package com.ruoyi.oauth.email.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.oauth.email.service.IMailService;
@RestController
@Anonymous
@RequestMapping("/mail")
public class MailController extends BaseController {
@Autowired
IMailService serviceImpl;
}

View File

@ -1,7 +0,0 @@
package com.ruoyi.oauth.email.service;
import com.ruoyi.oauth.common.service.OauthVerificationCodeService;
public interface IMailService extends OauthVerificationCodeService {
public boolean sendMimeMail(String email, String code);
}

View File

@ -1,153 +0,0 @@
package com.ruoyi.oauth.email.service.impl;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
import com.ruoyi.oauth.common.enums.OauthVerificationUse;
import com.ruoyi.oauth.email.service.IMailService;
import com.ruoyi.system.service.ISysUserService;
@Service
public class MailServiceImpl implements IMailService {
public String CACHE_NAME = "mail_codes";
@Autowired
private JavaMailSenderImpl mailSender;
@Autowired
private ISysUserService userService;
@Autowired
private TokenService tokenService;
@Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
private static final Logger log = LoggerFactory.getLogger(MailServiceImpl.class);
// application.properties配置的值
@Value("${spring.mail.username}")
private String from;
public boolean beforeSendCode(String email, OauthVerificationUse use) throws Exception {// 1.查验手机号是否存在分辨登录和删除用户以及注册用户
boolean haveEmailFlag = userService.selectUserByEmail(email) != null;
if ((use.equals(OauthVerificationUse.LOGIN) || use.equals(OauthVerificationUse.DISABLE)
|| use.equals(OauthVerificationUse.RESET_PASSWORD)) && !haveEmailFlag) {
throw new ServiceException("该邮箱未绑定用户");
} else if ((use.equals(OauthVerificationUse.REGISTER) || use.equals(OauthVerificationUse.RESET_PHONE))
&& haveEmailFlag) {
throw new ServiceException("该邮箱已绑定用户");
}
return true;
}
/**
* 给前端输入的邮箱发送验证码
*
* @param email
* @param session
* @return
*/
@Override
public boolean sendMimeMail(String email, String code) {
try {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setSubject("验证码邮件"); // 主题
simpleMailMessage.setText("您收到的验证码是:" + code); // 内容
simpleMailMessage.setFrom(from); // 发件人
simpleMailMessage.setTo(email); // 收件人
mailSender.send(simpleMailMessage); // 发送
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 随机生成6位数的验证码
*
* @return String code
*/
public static String generateRandomString(int n) {
String characters = "0123456789"; // ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
StringBuilder result = new StringBuilder();
Random random = new Random();
for (int i = 0; i < n; i++) {
int index = random.nextInt(characters.length());
result.append(characters.charAt(index));
}
return result.toString();
}
@Override
public boolean sendCode(String email, String code, OauthVerificationUse use) throws Exception {
// 限制短信一分钟只能发送一次短信
if (CacheUtils.hasKey(CACHE_NAME, email + use.getValue())) {
throw new ServiceException("请在1分钟后再发送短信");
}
try {
sendMimeMail(email, code);
CacheUtils.put(CACHE_NAME, email + use.getValue(), code, 1, TimeUnit.MINUTES);
log.info("发送邮箱验证码成功:{ phone: " + email + " code:" + code + "}");
return true;
} catch (Exception e) {
log.error("发送邮箱验证码异常:" + email);
throw e;
}
}
@Override
public String checkCode(String email, String code, OauthVerificationUse use) throws Exception {
String cachedCode = CacheUtils.get(use.getValue(), use.getValue() + email, String.class); // 从缓存中获取验证码
CacheUtils.remove(use.getValue(), use.getValue() + email);
boolean haveEmailFlag = userService.selectUserByEmail(email) != null;
if (use.equals(OauthVerificationUse.LOGIN) && haveEmailFlag) {// 登录校验
if (code.equals(cachedCode)) {
SysUser sysUser = userService.selectUserByEmail(email);
LoginUser loginUser = (LoginUser) userDetailsServiceImpl.createLoginUser(sysUser);
return tokenService.createToken(loginUser);
} else {
throw new ServiceException("验证码错误");
}
} else if (use.equals(OauthVerificationUse.REGISTER) && !haveEmailFlag) {// 注册校验
if (code.equals(cachedCode)) {
return Boolean.toString(true);
} else {
throw new ServiceException("验证码错误");
}
} else if (use.equals(OauthVerificationUse.DISABLE) && haveEmailFlag) {// 注销校验
if (code.equals(cachedCode)) {
return Boolean.toString(true);
} else {
throw new ServiceException("验证码错误");
}
} else if (use.equals(OauthVerificationUse.RESET_PASSWORD) && haveEmailFlag) {// 重置密码校验
if (code.equals(cachedCode)) {
return Boolean.toString(true);
} else {
throw new ServiceException("验证码错误");
}
} else if (use.equals(OauthVerificationUse.RESET_PHONE) && !haveEmailFlag) {// 重置账号校验
if (code.equals(cachedCode)) {
return Boolean.toString(true);
} else {
throw new ServiceException("验证码错误");
}
}
return Boolean.toString(false);
}
}

View File

@ -1,153 +0,0 @@
package com.ruoyi.oauth.phone.controller;
import java.util.Random;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.oauth.common.enums.OauthVerificationUse;
import com.ruoyi.oauth.phone.service.DySmsService;
import com.ruoyi.system.service.ISysUserService;
/**
* 手机号认证Controller
*
* @author zlh
* @date 2024-04-16
*/
@RestController
@RequestMapping("/oauth/phone")
public class DySmsController extends BaseController {
@Autowired
public DySmsService dySmsService;
@Autowired
private ISysUserService userService;
@Anonymous
@PostMapping("/sendcode/{mode}") // 发送验证码
public AjaxResult sendcode(@RequestBody LoginBody loginBody, @PathVariable(value = "mode") String mode)
throws Exception {
try {
OauthVerificationUse oauthVerificationUse = null;
switch (mode) {
case "login":
oauthVerificationUse = OauthVerificationUse.LOGIN;
break;
case "register":
oauthVerificationUse = OauthVerificationUse.REGISTER;
break;
case "disable":
oauthVerificationUse = OauthVerificationUse.DISABLE;
break;
case "resetpassword":
oauthVerificationUse = OauthVerificationUse.RESET_PASSWORD;
break;
case "resetphone":
oauthVerificationUse = OauthVerificationUse.RESET_PHONE;
break;
default:
oauthVerificationUse = OauthVerificationUse.Other;
}
String code = generateRandomString(6);
dySmsService.sendCode(loginBody.getUsername(), code, oauthVerificationUse);
return AjaxResult.success("发送验证码成功");
} catch (Exception e) {
return AjaxResult.error("发送验证码失败,原因: " + e.getMessage());
}
}
public static String generateRandomString(int n) {
String characters = "0123456789"; // ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
StringBuilder result = new StringBuilder();
Random random = new Random();
for (int i = 0; i < n; i++) {
int index = random.nextInt(characters.length());
result.append(characters.charAt(index));
}
return result.toString();
}
@Anonymous
@PostMapping("/login") // 登录
public AjaxResult postMethodName(@RequestBody LoginBody loginBody) throws Exception {
if (dySmsService.checkCode(loginBody.getUsername(), loginBody.getCode(),
OauthVerificationUse.LOGIN) == "false") {
return AjaxResult.error("登录失败");
} else {
return AjaxResult.success("登录成功");
}
}
@Anonymous
@PostMapping("/register") // 注册
public AjaxResult postenroll(@RequestBody LoginBody loginBody) throws Exception {
try {
dySmsService.checkCode(loginBody.getUsername(), loginBody.getCode(), OauthVerificationUse.REGISTER);
// 验证通过执行注册逻辑
SysUser user = new SysUser();
user.setUserName(loginBody.getUsername());
user.setNickName(loginBody.getUsername());
user.setPassword(SecurityUtils.encryptPassword(loginBody.getPassword()));
user.setPhonenumber(loginBody.getUsername());
userService.insertUser(user);
return AjaxResult.success("注册成功");
} catch (Exception e) {
// return "注册失败,原因: " + e.getMessage();
return AjaxResult.error("注册失败");
}
}
@PostMapping("/disable") // 注销
public AjaxResult postlogout(@RequestBody LoginBody loginBody) throws Exception {
try {
dySmsService.checkCode(getUsername(), loginBody.getCode(), OauthVerificationUse.DISABLE);
// 验证通过执行注销逻辑
SysUser sysUser = userService.selectUserByPhone(loginBody.getUsername());
userService.deleteUserById(sysUser.getUserId());
return AjaxResult.success("注销成功");
} catch (Exception e) {
return AjaxResult.error("注销失败,原因: " + e.getMessage());
}
}
@Anonymous
@PostMapping("/resetpassword") // 重置密码
public AjaxResult postpassword(@RequestBody LoginBody loginBody) throws Exception {
try {
dySmsService.checkCode(loginBody.getUsername(), loginBody.getCode(), OauthVerificationUse.RESET_PASSWORD);
// 验证通过执行重置密码逻辑
SysUser sysUser = userService.selectUserByPhone(loginBody.getUsername());
sysUser.setPassword(SecurityUtils.encryptPassword(loginBody.getPassword()));
userService.updateUser(sysUser);
return AjaxResult.success("重置密码成功");
} catch (Exception e) {
return AjaxResult.error("重置密码失败,原因: " + e.getMessage());
}
}
@PostMapping("/resetphone") // 重置手机号
public AjaxResult postphone(@RequestBody LoginBody loginBody) throws Exception {
try {
dySmsService.checkCode(loginBody.getUsername(), loginBody.getCode(), OauthVerificationUse.RESET_PHONE);
// 验证通过执行重置密码逻辑
SysUser sysUser = userService.selectUserByUserName(getUsername());
sysUser.setPhonenumber(loginBody.getUsername());
userService.updateUser(sysUser);
return AjaxResult.success("重置手机号成功");
} catch (Exception e) {
return AjaxResult.error("重置手机号失败,原因: " + e.getMessage());
}
}
}

View File

@ -1,14 +0,0 @@
package com.ruoyi.oauth.phone.service;
import com.ruoyi.oauth.common.service.OauthVerificationCodeService;
/**
* 手机号认证Servcie
*
* @author zlh
* @date 2024-04-16
*/
public interface DySmsService extends OauthVerificationCodeService {
public String doLogin(String phone);
}

View File

@ -1,183 +0,0 @@
package com.ruoyi.oauth.phone.service.Impl;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.CacheUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.framework.web.service.UserDetailsServiceImpl;
import com.ruoyi.oauth.common.enums.OauthVerificationUse;
import com.ruoyi.oauth.phone.enums.DySmsTemplate;
import com.ruoyi.oauth.phone.service.DySmsService;
import com.ruoyi.oauth.phone.utils.DySmsUtil;
import com.ruoyi.system.service.ISysUserService;
/**
* 手机号认证Servcie
*
* @author zlh
* @date 2024-04-16
*/
@Service
public class DySmsServiceImpl implements DySmsService {
@Autowired
private DySmsUtil dySmsUtil;
@Autowired
private ISysUserService userService;
@Autowired
private UserDetailsServiceImpl userDetailsServiceImpl;
@Autowired
private TokenService tokenService;
private static final String CACHE_NAME = "phone_codes";
private static final Logger log = LoggerFactory.getLogger(DySmsServiceImpl.class);
public boolean beforeSendCode(String phone, OauthVerificationUse use) throws Exception {// 1.查验手机号是否存在分辨登录和删除用户以及注册用户
boolean havePhoneFlag = userService.selectUserByPhone(phone) != null;
if ((use.equals(OauthVerificationUse.LOGIN) || use.equals(OauthVerificationUse.DISABLE)
|| use.equals(OauthVerificationUse.RESET_PASSWORD)) && !havePhoneFlag) {
throw new ServiceException("该手机号未绑定用户");
} else if ((use.equals(OauthVerificationUse.REGISTER) || use.equals(OauthVerificationUse.RESET_PHONE))
&& havePhoneFlag) {
throw new ServiceException("该手机号已绑定用户");
}
return true;
}
@Override
public boolean sendCode(String phone, String code, OauthVerificationUse use) throws Exception {// 1.查验手机号是否存在分辨登录和删除用户以及注册用户
// 限制短信一分钟只能发送一次短信
if (CacheUtils.hasKey(CACHE_NAME, phone + use.getValue())) {
throw new ServiceException("请在1分钟后再发送短信");
}
try {
JSONObject templateParams = new JSONObject();
templateParams.put("code", code);
dySmsUtil.sendSms(DySmsTemplate.Test_TEMPLATE_CODE, templateParams, phone);
CacheUtils.put(CACHE_NAME, phone + use.getValue(), code, 1, TimeUnit.MINUTES);
log.info("发送手机验证码成功:{ phone: " + phone + " code:" + code + "}");
return true;
} catch (Exception e) {
log.error("发送手机验证码异常:" + phone);
throw e;
}
}
@Override
public String checkCode(String phone, String code, OauthVerificationUse use) throws Exception {
String cachedCode = CacheUtils.get(use.getValue(), use.getValue() + phone, String.class); // 从缓存中获取验证码
CacheUtils.remove(use.getValue(), use.getValue() + phone);
boolean havePhoneFlag = userService.selectUserByPhone(phone) != null;
if (use.equals(OauthVerificationUse.LOGIN) && havePhoneFlag) {// 登录校验
if (code.equals(cachedCode)) {
SysUser sysUser = userService.selectUserByPhone(phone);
LoginUser loginUser = (LoginUser) userDetailsServiceImpl.createLoginUser(sysUser);
return tokenService.createToken(loginUser);
// return true;
} else {
throw new ServiceException("验证码错误");
}
} else if (use.equals(OauthVerificationUse.REGISTER) && !havePhoneFlag) {// 注册校验
if (code.equals(cachedCode)) {
return Boolean.toString(true);
} else {
throw new ServiceException("验证码错误");
}
} else if (use.equals(OauthVerificationUse.DISABLE) && havePhoneFlag) {// 注销校验
if (code.equals(cachedCode)) {
return Boolean.toString(true);
} else {
throw new ServiceException("验证码错误");
}
} else if (use.equals(OauthVerificationUse.RESET_PASSWORD) && havePhoneFlag) {// 重置密码校验
if (code.equals(cachedCode)) {
return Boolean.toString(true);
} else {
throw new ServiceException("验证码错误");
}
} else if (use.equals(OauthVerificationUse.RESET_PHONE) && !havePhoneFlag) {// 重置账号校验
if (code.equals(cachedCode)) {
return Boolean.toString(true);
} else {
throw new ServiceException("验证码错误");
}
}
return Boolean.toString(false);
}
public static String generateRandomString(int n) {
String characters = "0123456789"; // ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
StringBuilder result = new StringBuilder();
Random random = new Random();
for (int i = 0; i < n; i++) {
int index = random.nextInt(characters.length());
result.append(characters.charAt(index));
}
return result.toString();
}
@Override
public String doLogin(String phone) {
String verify = CacheUtils.get(CACHE_NAME, phone + OauthVerificationUse.LOGIN, String.class);
if (verify != null) {
throw new ServiceException("该手机号验证码未过期");
}
String code = generateRandomString(6);
SysUser sysUser = userService.selectUserByPhone(phone);
if (sysUser == null) {
throw new ServiceException("该手机号未绑定用户");
}
try {
JSONObject templateParams = new JSONObject();
templateParams.put("code", code);
dySmsUtil.sendSms(DySmsTemplate.Test_TEMPLATE_CODE, templateParams, phone);
CacheUtils.put(CACHE_NAME, phone + OauthVerificationUse.LOGIN, code, 1,
TimeUnit.MINUTES);
} catch (Exception e) {
e.printStackTrace();
}
return code;
}
public String doLoginVerify(String phone, String code) {
String verify = CacheUtils.get(CACHE_NAME, phone + OauthVerificationUse.LOGIN, String.class);
if (code.equals(verify)) {
SysUser sysUser = userService.selectUserByPhone(phone);
LoginUser loginUser = (LoginUser) userDetailsServiceImpl.createLoginUser(sysUser);
return tokenService.createToken(loginUser);
} else {
throw new ServiceException("验证码错误");
}
}
public String doRegister(String phone) {
String code = generateRandomString(6);
CacheUtils.put(CACHE_NAME, phone + OauthVerificationUse.REGISTER, code, 1, TimeUnit.MINUTES);
String verify = CacheUtils.get("phone_codes_register", phone, String.class);
if (verify != null) {
throw new ServiceException("该手机号验证码未过期");
} else {
try {
dySmsUtil.sendSms(null, null, phone);
CacheUtils.put(CACHE_NAME, phone + OauthVerificationUse.REGISTER, code, 1, TimeUnit.MINUTES);
} catch (Exception e) {
e.printStackTrace();
}
}
return code;
}
}