{"id":10006628,"date":"2022-09-28T18:44:28","date_gmt":"2022-09-28T10:44:28","guid":{"rendered":"https:\/\/ityet.com\/?p=10006628"},"modified":"2022-09-28T18:44:28","modified_gmt":"2022-09-28T10:44:28","slug":"spring-security-jwt-%e5%ae%9e%e7%8e%b0%e4%b8%80%e4%b8%aa%e6%9d%83%e9%99%90%e7%b3%bb%e7%bb%9f%ef%bc%8c%e5%86%99%e7%9a%84%e5%a4%aa%e5%a5%bd%e4%ba%86%e5%90%a7%ef%bc%81","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10006628","title":{"rendered":"Spring Security + JWT \u5b9e\u73b0\u4e00\u4e2a\u6743\u9650\u7cfb\u7edf\uff0c\u5199\u7684\u592a\u597d\u4e86\u5427\uff01"},"content":{"rendered":"<p>\u4f5c\u8005\uff1a\u5c0f\u5c0f____\/<br \/>\u6765\u6e90\uff1asegmentfault.com\/a\/1190000023052493<\/p>\n<p>\u601d\u7ef4\u5bfc\u56fe\u5982\u4e0b<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1q\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<h2>RBAC\u6743\u9650\u5206\u6790<\/h2>\n<p>RBAC \u5168\u79f0\u4e3a\u57fa\u4e8e\u89d2\u8272\u7684\u6743\u9650\u63a7\u5236\uff0c\u672c\u6bb5\u5c06\u4f1a\u4ece\u4ec0\u4e48\u662fRBAC\uff0c\u6a21\u578b\u5206\u7c7b\uff0c\u4ec0\u4e48\u662f\u6743\u9650\uff0c\u7528\u6237\u7ec4\u7684\u4f7f\u7528\uff0c\u5b9e\u4f8b\u5206\u6790\u7b49\u51e0\u4e2a\u65b9\u9762\u9610\u8ff0RBAC<\/p>\n<h3>\u601d\u7ef4\u5bfc\u56fe<\/h3>\n<p>\u7ed8\u5236\u601d\u7ef4\u5bfc\u56fe\u5982\u4e0b<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1r\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<h3>\u4ec0\u4e48\u662fRBAC<\/h3>\n<p>RBAC \u5168\u79f0\u4e3a\u7528\u6237\u89d2\u8272\u6743\u9650\u63a7\u5236\uff0c\u901a\u8fc7\u89d2\u8272\u5173\u8054\u7528\u6237\uff0c\u89d2\u8272\u5173\u8054\u6743\u9650\uff0c\u8fd9\u79cd\u65b9\u5f0f\uff0c\u95f4\u9636\u7684\u8d4b\u4e88\u7528\u6237\u7684\u6743\u9650\uff0c\u5982\u4e0b\u56fe\u6240\u793a<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1s\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<p>\u5bf9\u4e8e\u901a\u5e38\u7684\u7cfb\u7edf\u800c\u8a00\uff0c\u5b58\u5728\u591a\u4e2a\u7528\u6237\u5177\u6709\u76f8\u540c\u7684\u6743\u9650\uff0c\u5728\u5206\u914d\u7684\u65f6\u5019\uff0c\u8981\u4e3a\u6307\u5b9a\u7684\u7528\u6237\u5206\u914d\u76f8\u5173\u7684\u6743\u9650\uff0c\u4fee\u6539\u7684\u65f6\u5019\u4e5f\u8981\u4f9d\u6b21\u7684\u5bf9\u8fd9\u51e0\u4e2a\u7528\u6237\u7684\u6743\u9650\u8fdb\u884c\u4fee\u6539\uff0c\u6709\u4e86\u89d2\u8272\u8fd9\u4e2a\u6743\u9650\uff0c\u5728\u4fee\u6539\u6743\u9650\u7684\u65f6\u5019\uff0c\u53ea\u9700\u8981\u5bf9\u89d2\u8272\u8fdb\u884c\u4fee\u6539\uff0c\u5c31\u53ef\u4ee5\u5b9e\u73b0\u76f8\u5173\u7684\u6743\u9650\u7684\u4fee\u6539\u3002\u8fd9\u6837\u505a\u589e\u52a0\u4e86\u6548\u7387\uff0c\u51cf\u5c11\u4e86\u6743\u9650\u6f0f\u6d1e\u7684\u53d1\u751f\u3002<\/p>\n<h3>\u6a21\u578b\u5206\u7c7b<\/h3>\n<p>\u5bf9\u4e8eRBAC\u6a21\u578b\u6765\u8bf4\uff0c\u5206\u4e3a\u4ee5\u4e0b\u51e0\u4e2a\u6a21\u578b \u5206\u522b\u662fRBAC0\uff0cRBAC1\uff0cRBAC2\uff0cRBAC3\uff0c\u8fd9\u56db\u4e2a\u6a21\u578b\uff0c\u8fd9\u6bb5\u5c06\u4f1a\u4f9d\u6b21\u4ecb\u7ecd\u8fd9\u56db\u4e2a\u6a21\u578b\uff0c\u5176\u4e2d\u6700\u5e38\u7528\u7684\u6a21\u578b\u6709RBAC0.<\/p>\n<h4>RBAC0<\/h4>\n<p>RBAC0\u662f\u6700\u7b80\u5355\u7684RBAC\u6a21\u578b\uff0c\u8fd9\u91cc\u9762\u5305\u542b\u4e86\u4e24\u79cd\u3002<\/p>\n<p>\u7528\u6237\u548c\u89d2\u8272\u662f\u591a\u5bf9\u4e00\u7684\u5173\u7cfb\uff0c\u5373\u4e00\u4e2a\u7528\u6237\u53ea\u5145\u5f53\u4e00\u79cd\u89d2\u8272\uff0c\u4e00\u4e2a\u89d2\u8272\u53ef\u4ee5\u6709\u591a\u4e2a\u89d2\u8272\u7684\u62c5\u5f53\u3002<br \/>\u7528\u6237\u548c\u89d2\u8272\u662f\u591a\u5bf9\u591a\u7684\u5173\u7cfb\uff0c\u5373\uff0c\u4e00\u4e2a\u7528\u6237\u53ef\u4ee5\u540c\u65f6\u5145\u5f53\u591a\u4e2a\u89d2\u8272\uff0c\u4e00\u4e2a\u89d2\u8272\u53ef\u4ee5\u6709\u591a\u4e2a\u7528\u6237\u3002<br \/>\u6b64\u7cfb\u7edf\u529f\u80fd\u5355\u4e00\uff0c\u4eba\u5458\u8f83\u5c11\uff0c\u8fd9\u91cc\u4e3e\u4e2a\u6817\u5b50\uff0c\u5f20\u4e09\u65e2\u662f\u884c\u653f\uff0c\u4e5f\u8d1f\u8d23\u8d22\u52a1\uff0c\u6b64\u65f6\u5f20\u4e09\u5c31\u6709\u4fe9\u4e2a\u6743\u9650\uff0c\u5206\u522b\u662f\u884c\u653f\u6743\u9650\uff0c\u548c\u8d22\u52a1\u6743\u9650\u4e24\u4e2a\u90e8\u5206\u3002<\/p>\n<h4>RBAC1<\/h4>\n<p>\u76f8\u5bf9\u4e8eRBAC0\u6a21\u578b\u6765\u8bf4\uff0c\u589e\u52a0\u4e86\u5b50\u89d2\u8272\uff0c\u5f15\u5165\u4e86\u7ee7\u627f\u7684\u6982\u5ff5\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1t\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<h4>RBAC2 \u6a21\u578b<\/h4>\n<p>\u8fd9\u91ccRBAC2\u6a21\u578b\uff0c\u5728RBAC0\u6a21\u578b\u7684\u57fa\u7840\u4e0a\uff0c\u589e\u52a0\u4e86\u4e00\u4e9b\u529f\u80fd\uff0c\u4ee5\u53ca\u9650\u5236<\/p>\n<h5>\u89d2\u8272\u4e92\u65a5<\/h5>\n<p>\u5373\uff0c\u540c\u4e00\u4e2a\u7528\u6237\u4e0d\u80fd\u62e5\u6709\u4e24\u4e2a\u4e92\u65a5\u7684\u89d2\u8272\uff0c\u4e3e\u4e2a\u4f8b\u5b50\uff0c\u5728\u8d22\u52a1\u7cfb\u7edf\u4e2d\uff0c\u4e00\u4e2a\u7528\u6237\u4e0d\u80fd\u62e5\u6709\u4f1a\u8ba1\u5458\u548c\u5ba1\u8ba1\u8fd9\u4e24\u79cd\u89d2\u8272\u3002<\/p>\n<h5>\u57fa\u6570\u7ea6\u675f<\/h5>\n<p>\u5373\uff0c\u7528\u4e00\u4e2a\u89d2\u8272\uff0c\u6240\u62e5\u6709\u7684\u6210\u5458\u662f\u56fa\u5b9a\u7684\uff0c\u4f8b\u5982\u5bf9\u4e8eCEO\u8fd9\u79cd\u89d2\u8272\uff0c\u540c\u4e00\u4e2a\u89d2\u8272\uff0c\u4e5f\u53ea\u80fd\u6709\u4e00\u4e2a\u7528\u6237\u3002<\/p>\n<h5>\u5148\u51b3\u6761\u4ef6<\/h5>\n<p>\u5373\uff0c\u5bf9\u4e8e\u8be5\u89d2\u8272\u6765\u8bf4\uff0c\u5982\u679c\u60f3\u8981\u83b7\u5f97\u66f4\u9ad8\u7684\u89d2\u8272\uff0c\u9700\u8981\u5148\u83b7\u53d6\u4f4e\u4e00\u7ea7\u522b\u7684\u89d2\u8272\u3002\u4e3e\u4e2a\u6817\u5b50\uff0c\u5bf9\u4e8e\u526f\u603b\u7ecf\u7406\u548c\u7ecf\u7406\u8fd9\u4e24\u4e2a\u6743\u9650\u6765\u8bf4\uff0c\u9700\u8981\u5148\u6709\u526f\u603b\u7ecf\u7406\u6743\u9650\uff0c\u624d\u80fd\u62e5\u6709\u7ecf\u7406\u6743\u9650\uff0c\u5176\u4e2d\u526f\u603b\u7ecf\u7406\u6743\u9650\u662f\u7ecf\u7406\u6743\u9650\u7684\u5148\u51b3\u6761\u4ef6\u3002<\/p>\n<h5>\u8fd0\u884c\u65f6\u4e92\u65a5<\/h5>\n<p>\u5373\uff0c\u4e00\u4e2a\u7528\u6237\u53ef\u4ee5\u62e5\u6709\u4e24\u4e2a\u89d2\u8272\uff0c\u4f46\u662f\u8fd9\u4fe9\u4e2a\u89d2\u8272\u4e0d\u80fd\u540c\u65f6\u4f7f\u7528\uff0c\u9700\u8981\u5207\u6362\u89d2\u8272\u624d\u80fd\u8fdb\u5165\u53e6\u5916\u4e00\u4e2a\u89d2\u8272\u3002\u4e3e\u4e2a\u6817\u5b50\uff0c\u5bf9\u4e8e\u603b\u7ecf\u7406\u548c\u4e13\u5458\u8fd9\u4e24\u4e2a\u89d2\u8272\uff0c\u7cfb\u7edf\u53ea\u80fd\u5728\u4e00\u6bb5\u65f6\u95f4\uff0c\u62e5\u6709\u5176\u4e00\u4e2a\u89d2\u8272\uff0c\u4e0d\u80fd\u540c\u65f6\u5bf9\u8fd9\u4e24\u79cd\u89d2\u8272\u8fdb\u884c\u64cd\u4f5c\u3002<\/p>\n<h4>RBAC3\u6a21\u578b<\/h4>\n<p>\u5373\uff0cRBAC1\uff0cRBAC2\uff0c\u4e24\u8005\u6a21\u578b\u5168\u90e8\u7d2f\u8ba1\uff0c\u79f0\u4e3a\u7edf\u4e00\u6a21\u578b\u3002<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1u\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<h4>\u4ec0\u4e48\u662f\u6743\u9650<\/h4>\n<p>\u6743\u9650\u662f\u8d44\u6e90\u7684\u96c6\u5408\uff0c\u8fd9\u91cc\u7684\u8d44\u6e90\u6307\u7684\u662f\u8f6f\u4ef6\u4e2d\u7684\u6240\u6709\u7684\u5185\u5bb9\uff0c\u5373\uff0c\u5bf9\u9875\u9762\u7684\u64cd\u4f5c\u6743\u9650\uff0c\u5bf9\u9875\u9762\u7684\u8bbf\u95ee\u6743\u9650\uff0c\u5bf9\u6570\u636e\u7684\u589e\u5220\u67e5\u6539\u7684\u6743\u9650\u3002 \u4e3e\u4e2a\u6817\u5b50\u3002 \u5bf9\u4e8e\u4e0b\u56fe\u4e2d\u7684\u7cfb\u7edf\u800c\u8a00\uff0c<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1v\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<p>\u62e5\u6709\uff0c\u8ba1\u5212\u7ba1\u7406\uff0c\u5ba2\u6237\u7ba1\u7406\uff0c\u5408\u540c\u7ba1\u7406\uff0c\u51fa\u5165\u5e93\u901a\u77e5\u5355\u7ba1\u7406\uff0c\u7cae\u98df\u5b89\u5168\u8ffd\u6eaf\uff0c\u7cae\u98df\u7edf\u8ba1\u67e5\u8be2\uff0c\u8bbe\u5907\u7ba1\u7406\u8fd9\u51e0\u4e2a\u9875\u9762\uff0c\u5bf9\u8fd9\u51e0\u4e2a\u9875\u9762\u7684\u8bbf\u95ee\uff0c\u4ee5\u53ca\u662f\u5426\u80fd\u591f\u8bbf\u95ee\u5230\u83dc\u5355\uff0c\u90fd\u5c5e\u4e8e\u6743\u9650\u3002<\/p>\n<h4>\u7528\u6237\u7ec4\u7684\u4f7f\u7528<\/h4>\n<p>\u5bf9\u4e8e\u7528\u6237\u7ec4\u6765\u8bf4\uff0c\u662f\u628a\u4f17\u591a\u7684\u7528\u6237\u5212\u5206\u4e3a\u4e00\u7ec4\uff0c\u8fdb\u884c\u6279\u91cf\u6388\u4e88\u89d2\u8272\uff0c\u5373\uff0c\u6279\u91cf\u6388\u4e88\u6743\u9650\u3002 \u4e3e\u4e2a\u6817\u5b50\uff0c\u5bf9\u4e8e\u90e8\u95e8\u6765\u8bf4\uff0c\u4e00\u4e2a\u90e8\u95e8\u62e5\u6709\u4e00\u4e07\u591a\u4e2a\u5458\u5de5\uff0c\u8fd9\u4e9b\u5458\u5de5\u90fd\u62e5\u6709\u76f8\u540c\u7684\u89d2\u8272\uff0c\u5982\u679c\u6ca1\u6709\u7528\u6237\u7ec4\uff0c\u53ef\u80fd\u9700\u8981\u4e00\u4e2a\u4e2a\u7684\u6388\u4e88\u76f8\u5173\u7684\u89d2\u8272\uff0c\u5728\u62e5\u6709\u4e86\u7528\u6237\u7ec4\u4ee5\u540e\uff0c\u53ea\u9700\u8981\uff0c\u628a\u8fd9\u4e9b\u7528\u6237\u5168\u90e8\u5212\u5206\u4e3a\u4e00\u7ec4\uff0c\u7136\u540e\u5bf9\u8be5\u7ec4\u8bbe\u7f6e\u6388\u4e88\u89d2\u8272\uff0c\u5c31\u7b49\u540c\u4e8e\u5bf9\u8fd9\u4e9b\u7528\u6237\u6388\u4e88\u89d2\u8272\u3002<\/p>\n<p>\u4f18\u70b9\uff1a \u51cf\u5c11\u5de5\u4f5c\u91cf\uff0c\u4fbf\u4e8e\u7406\u89e3\uff0c\u589e\u52a0\u591a\u7ea7\u7ba1\u7406\uff0c\u7b49\u3002<\/p>\n<h2>SpringSecurity \u7b80\u5355\u4f7f\u7528<\/h2>\n<p>\u9996\u5148\u6dfb\u52a0\u4f9d\u8d56<\/p>\n<p>Spring Boot \u57fa\u7840\u5c31\u4e0d\u4ecb\u7ecd\u4e86\uff0c\u63a8\u8350\u4e0b\u8fd9\u4e2a\u5b9e\u6218\u6559\u7a0b\uff1a<br \/><a href=\"https:\/\/link.segmentfault.com\/?enc=Cs8LxVcSSP%2FDrxz%2FWEMvkQ%3D%3D.2OsoXAD%2BFKKjaai7W2TbWvpDIpJIlVabZ6yNxk4PsihUoRGUnMTzJocXTB0HZ2XRDORRybnujx2MhF%2FzNdZFzw%3D%3D\" rel=\"nofollow\">https:\/\/github.com\/javastacks&#8230;<\/a><\/p>\n<pre><code class=\"xml\">&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-boot-starter-security&lt;\/artifactId&gt;\n&lt;\/dependency&gt;<\/code><\/pre>\n<p>\u7136\u540e\u6dfb\u52a0\u76f8\u5173\u7684\u8bbf\u95ee\u63a5\u53e3<\/p>\n<pre><code class=\"kotlin\">package com.example.demo.web;\n\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(&quot;\/test&quot;)\npublic class Test {\n    @RequestMapping(&quot;\/test&quot;)\n    public String test(){\n        return &quot;test&quot;;\n    }\n}<\/code><\/pre>\n<p>\u6700\u540e\u542f\u52a8\u9879\u76ee\uff0c\u5728\u65e5\u5fd7\u4e2d\u67e5\u770b\u76f8\u5173\u7684\u5bc6\u7801<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1w\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<p>\u8bbf\u95ee\u63a5\u53e3\uff0c\u53ef\u4ee5\u770b\u5230\u76f8\u5173\u7684\u767b\u5f55\u754c\u9762<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1x\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<p>\u8f93\u5165\u7528\u6237\u540d\u548c\u76f8\u5173\u7684\u5bc6\u7801<\/p>\n<pre><code class=\"crmsh\">\u7528\u6237\u540d\uff1a user\n\u5bc6\u7801 984cccf2-ba82-468e-a404-7d32123d0f9c<\/code><\/pre>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1y\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<p>\u767b\u5f55\u6210\u529f<\/p>\n<h3>\u589e\u52a0\u7528\u6237\u540d\u548c\u5bc6\u7801<\/h3>\n<p>\u5728\u914d\u7f6e\u6587\u4ef6\u4e2d\uff0c\u4e66\u5199\u76f8\u5173\u7684\u767b\u5f55\u548c\u5bc6\u7801<\/p>\n<pre><code class=\"dts\">spring:\n  security:\n    user:\n      name: ming\n      password: 123456\n      roles: admin\n<\/code><\/pre>\n<p>\u5728\u767b\u5f55\u9875\u9762\uff0c\u8f93\u5165\u7528\u6237\u540d\u548c\u5bc6\u7801\uff0c\u5373\u53ef\u6b63\u5e38\u767b\u5f55<\/p>\n<h3>\u57fa\u4e8e\u5185\u5b58\u7684\u8ba4\u8bc1<\/h3>\n<p>\u9700\u8981\u81ea\u5b9a\u4e49\u7c7b\u7ee7\u627f WebSecurityConfigurerAdapter \u4ee3\u7801\u5982\u4e0b<\/p>\n<pre><code class=\"scala\">package com.example.demo.config;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.crypto.password.NoOpPasswordEncoder;\nimport org.springframework.security.crypto.password.PasswordEncoder;\n\n@Configuration\npublic class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {\n    @Bean\n    PasswordEncoder passwordEncoder(){\n        return NoOpPasswordEncoder.getInstance();\n    }\n\n    @Override\n    protected void configure(AuthenticationManagerBuilder auth) throws Exception {\n        auth.inMemoryAuthentication()\n                .withUser(&quot;admin&quot;).password(&quot;123&quot;).roles(&quot;admin&quot;);\n    }\n}<\/code><\/pre>\n<p>\u5373\uff0c\u914d\u7f6e\u7684\u7528\u6237\u540d\u4e3aadmin\uff0c\u5bc6\u7801\u4e3a123\uff0c\u89d2\u8272\u4e3aadmin<\/p>\n<h3>HttpSecurity<\/h3>\n<p>\u8fd9\u91cc\u5bf9\u4e00\u4e9b\u65b9\u6cd5\u8fdb\u884c\u62e6\u622a<\/p>\n<pre><code class=\"pgsql\">package com.ming.demo.interceptor;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.http.HttpMethod;\nimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\nimport org.springframework.security.crypto.password.PasswordEncoder;\nimport org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;\n\n@Configuration\n@EnableWebSecurity\npublic class SecurityConfig  extends WebSecurityConfigurerAdapter {\n    \/\/\u57fa\u4e8e\u5185\u5b58\u7684\u7528\u6237\u5b58\u50a8\n    @Override\n    public void configure(AuthenticationManagerBuilder auth) throws Exception {\n        auth.inMemoryAuthentication()\n                .withUser(&quot;itguang&quot;).password(&quot;123456&quot;).roles(&quot;USER&quot;).and()\n                .withUser(&quot;admin&quot;).password(&quot;{noop}&quot; + &quot;123456&quot;).roles(&quot;ADMIN&quot;);\n    }\n\n    \/\/\u8bf7\u6c42\u62e6\u622a\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http.authorizeRequests()\n                .anyRequest().permitAll()\n                .and()\n                .formLogin()\n                .permitAll()\n                .and()\n                .logout()\n                .permitAll();\n    }\n\n}<\/code><\/pre>\n<p>\u5373\uff0c\u8fd9\u91cc\u5b8c\u6210\u4e86\u5bf9\u6240\u6709\u7684\u65b9\u6cd5\u8bbf\u95ee\u7684\u62e6\u622a\u3002<\/p>\n<h2>SpringSecurity \u96c6\u6210JWT<\/h2>\n<p>\u8fd9\u662f\u4e00\u4e2a\u5c0fdemo\uff0c\u76ee\u7684\uff0c\u767b\u5f55\u4ee5\u540e\u8fd4\u56dejwt\u751f\u6210\u7684token<\/p>\n<h3>\u5bfc\u5165\u4f9d\u8d56<\/h3>\n<p>\u6dfb\u52a0web\u4f9d\u8d56<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1z\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<p>\u5bfc\u5165JWT\u548cSecurity\u4f9d\u8d56<\/p>\n<pre><code class=\"xml\"> &lt;!-- https:\/\/mvnrepository.com\/artifact\/io.jsonwebtoken\/jjwt --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;io.jsonwebtoken&lt;\/groupId&gt;\n            &lt;artifactId&gt;jjwt&lt;\/artifactId&gt;\n            &lt;version&gt;0.9.1&lt;\/version&gt;\n        &lt;\/dependency&gt;\n        &lt;!-- https:\/\/mvnrepository.com\/artifact\/org.springframework.boot\/spring-boot-starter-security --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-security&lt;\/artifactId&gt;\n            &lt;version&gt;2.3.1.RELEASE&lt;\/version&gt;\n        &lt;\/dependency&gt;<\/code><\/pre>\n<h3>\u521b\u5efa\u4e00\u4e2aJwtUser\u5b9e\u73b0UserDetails<\/h3>\n<p>\u521b\u5efa \u4e00\u4e2a\u76f8\u5173\u7684JavaBean<\/p>\n<pre><code class=\"typescript\">package com.example.demo;\n\nimport org.springframework.security.core.GrantedAuthority;\nimport org.springframework.security.core.userdetails.UserDetails;\n\nimport java.util.Collection;\n\npublic class JwtUser implements UserDetails {\n    private String username;\n    private String password;\n    private Integer state;\n    private Collection&lt;? extends GrantedAuthority&gt; authorities;\n    public JwtUser(){\n\n    }\n\n    public JwtUser(String username, String password, Integer state,  Collection&lt;? extends GrantedAuthority&gt; authorities){\n        this.username = username;\n        this.password = password;\n        this.state = state;\n        this.authorities = authorities;\n    }\n\n    @Override\n    public Collection&lt;? extends GrantedAuthority&gt; getAuthorities() {\n        return authorities;\n    }\n\n    @Override\n    public String getPassword() {\n        return this.password;\n    }\n\n    @Override\n    public String getUsername() {\n        return this.username;\n    }\n\n    @Override\n    public boolean isAccountNonExpired() {\n        return true;\n    }\n\n    @Override\n    public boolean isAccountNonLocked() {\n        return true;\n    }\n\n    @Override\n    public boolean isCredentialsNonExpired() {\n        return true;\n    }\n\n    @Override\n    public boolean isEnabled() {\n        return true;\n    }\n}<\/code><\/pre>\n<h3>\u7f16\u5199\u5de5\u5177\u7c7b\u751f\u6210\u4ee4\u724c<\/h3>\n<p>\u7f16\u5199\u5de5\u5177\u7c7b\uff0c\u7528\u6765\u751f\u6210token\uff0c\u4ee5\u53ca\u5237\u65b0token\uff0c\u4ee5\u53ca\u9a8c\u8bc1token<\/p>\n<pre><code class=\"typescript\">package com.example.demo;\n\nimport io.jsonwebtoken.Claims;\nimport io.jsonwebtoken.Jwts;\nimport io.jsonwebtoken.SignatureAlgorithm;\nimport org.springframework.security.core.userdetails.UserDetails;\n\nimport java.io.Serializable;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class JwtTokenUtil implements Serializable {\n    private String secret;\n    private Long expiration;\n    private String header;\n\n    private String generateToken(Map&lt;String, Object&gt; claims) {\n        Date expirationDate = new Date(System.currentTimeMillis() + expiration);\n        return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, secret).compact();\n    }\n\n    private Claims getClaimsFromToken(String token) {\n        Claims claims;\n        try {\n            claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();\n\n        } catch (Exception e) {\n            claims = null;\n        }\n        return claims;\n    }\n\n    public String generateToken(UserDetails userDetails) {\n        Map&lt;String, Object&gt; claims = new HashMap&lt;&gt;(2);\n        claims.put(&quot;sub&quot;, userDetails.getUsername());\n        claims.put(&quot;created&quot;, new Date());\n        return generateToken(claims);\n\n    }\n\n    public String getUsernameFromToken(String token) {\n        String username;\n        try {\n            Claims claims = getClaimsFromToken(token);\n            username = claims.getSubject();\n\n        } catch (Exception e) {\n            username = null;\n\n        }\n        return username;\n\n    }\n\n    public Boolean isTokenExpired(String token) {\n        try {\n            Claims claims = getClaimsFromToken(token);\n            Date expiration = claims.getExpiration();\n            return expiration.before(new Date());\n        } catch (Exception e) {\n            return false;\n        }\n    }\n\n    public String refreshToken(String token) {\n        String refreshedToken;\n        try {\n            Claims claims = getClaimsFromToken(token);\n            claims.put(&quot;created&quot;, new Date());\n            refreshedToken = generateToken(claims);\n\n        } catch (Exception e) {\n            refreshedToken = null;\n\n        }\n        return refreshedToken;\n    }\n\n    public Boolean validateToken(String token, UserDetails userDetails) {\n        JwtUser user = (JwtUser) userDetails;\n        String username = getUsernameFromToken(token);\n        return (username.equals(user.getUsername()) &amp;&amp; !isTokenExpired(token));\n\n    }\n\n}<\/code><\/pre>\n<h3>\u7f16\u5199\u62e6\u622a\u5668<\/h3>\n<p>\u7f16\u5199Filter \u7528\u6765\u68c0\u6d4bJWT<\/p>\n<pre><code class=\"reasonml\">package com.example.demo;\n\nimport org.apache.commons.lang.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.security.core.userdetails.UserDetails;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.web.authentication.WebAuthenticationDetailsSource;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.filter.OncePerRequestFilter;\n\nimport javax.servlet.FilterChain;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n@Component\npublic class JwtAuthenticationTokenFilter  extends OncePerRequestFilter {\n    @Autowired\n    private UserDetailsService userDetailsService;\n    @Autowired\n    private JwtTokenUtil jwtTokenUtil;\n\n    @Override\n    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {\n        String authHeader = httpServletRequest.getHeader(jwtTokenUtil.getHeader());\n        if (authHeader != null &amp;&amp; StringUtils.isNotEmpty(authHeader)) {\n            String username = jwtTokenUtil.getUsernameFromToken(authHeader);\n            if (username != null &amp;&amp; SecurityContextHolder.getContext().getAuthentication() == null) {\n                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);\n                if (jwtTokenUtil.validateToken(authHeader, userDetails)) {\n                    UsernamePasswordAuthenticationToken authentication  =\n                    new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());\n                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));\n                    SecurityContextHolder.getContext().setAuthentication(authentication);\n\n                }\n            }\n        }\n        filterChain.doFilter(httpServletRequest, httpServletResponse);\n\n    }\n}<\/code><\/pre>\n<h3>\u7f16\u5199userDetailsService\u7684\u5b9e\u73b0\u7c7b<\/h3>\n<p>\u5728\u4e0a\u65b9\u4ee3\u7801\u4e2d\uff0c\u7f16\u5199userDetailsService\uff0c\u7c7b\uff0c\u5b9e\u73b0\u5176\u9a8c\u8bc1\u8fc7\u7a0b<\/p>\n<pre><code class=\"pgsql\">package com.example.demo;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.core.authority.SimpleGrantedAuthority;\nimport org.springframework.security.core.userdetails.User;\nimport org.springframework.security.core.userdetails.UserDetails;\nimport org.springframework.security.core.userdetails.UserDetailsService;\nimport org.springframework.security.core.userdetails.UsernameNotFoundException;\nimport org.springframework.stereotype.Service;\n\nimport javax.management.relation.Role;\nimport java.util.List;\n\n@Service\npublic class JwtUserDetailsServiceImpl  implements UserDetailsService {\n    @Autowired\n    private UserMapper userMapper;\n\n    @Override\n    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {\n        User user = userMapper.selectByUserName(s);\n        if (user == null) {\n            throw new UsernameNotFoundException(String.format(&quot;'%s'.\u8fd9\u4e2a\u7528\u6237\u4e0d\u5b58\u5728&quot;, s));\n\n        }\n        List&lt;SimpleGrantedAuthority&gt; collect = user.getRoles().stream().map(Role::getRolename).map(SimpleGrantedAuthority::new).collect(Collectors.toList());\n        return new JwtUser(user.getUsername(), user.getPassword(), user.getState(), collect);\n\n    }\n}<\/code><\/pre>\n<h3>\u7f16\u5199\u767b\u5f55<\/h3>\n<p>\u7f16\u5199\u767b\u5f55\u4e1a\u52a1\u7684\u5b9e\u73b0\u7c7b \u5176login\u65b9\u6cd5\u4f1a\u8fd4\u56de\u4e00\u4e2aJWTUtils \u7684token<\/p>\n<pre><code class=\"java\">@Service\npublic class UserServiceImpl  implements UserService {\n    @Autowired\n    private UserMapper userMapper;\n\n    @Autowired\n    private AuthenticationManager authenticationManager;\n\n    @Autowired\n    private UserDetailsService userDetailsService;\n\n    @Autowired\n    private JwtTokenUtil jwtTokenUtil;\n\n    public User findByUsername(String username) {\n        User user = userMapper.selectByUserName(username);\n        return user;\n\n    }\n\n    public RetResult login(String username, String password) throws AuthenticationException {\n        UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);\n        final Authentication authentication = authenticationManager.authenticate(upToken);\n        SecurityContextHolder.getContext().setAuthentication(authentication);\n        UserDetails userDetails = userDetailsService.loadUserByUsername(username);\n        return new RetResult(RetCode.SUCCESS.getCode(),jwtTokenUtil.generateToken(userDetails));\n\n    }\n}<\/code><\/pre>\n<h3>\u6700\u540e\u914d\u7f6eConfig<\/h3>\n<pre><code class=\"reasonml\">@EnableGlobalMethodSecurity(prePostEnabled = true)\n@EnableWebSecurity\npublic class WebSecurity extends WebSecurityConfigurerAdapter {\n    @Autowired\n    private UserDetailsService userDetailsService;\n    @Autowired\n    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;\n\n    @Autowired\n    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {\n        authenticationManagerBuilder.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder());\n\n    }\n\n    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)\n\n    @Override\n    public AuthenticationManager authenticationManagerBean() throws Exception {\n        return super.authenticationManagerBean();\n    }\n\n    @Bean\n    public PasswordEncoder passwordEncoder() {\n        return new BCryptPasswordEncoder();\n\n    }\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)\n                .and().authorizeRequests()\n                .antMatchers(HttpMethod.OPTIONS, &quot;\/**&quot;).permitAll()\n                .antMatchers(&quot;\/auth\/**&quot;).permitAll()\n                .anyRequest().authenticated()\n                .and().headers().cacheControl();\n\n        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);\n\n        ExpressionUrlAuthorizationConfigurer&lt;HttpSecurity&gt;.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();\n\n        registry.requestMatchers(CorsUtils::isPreFlightRequest).permitAll();\n\n    }\n\n    @Bean\n    public CorsFilter corsFilter() {\n        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();\n        final CorsConfiguration cors = new CorsConfiguration();\n        cors.setAllowCredentials(true);\n        cors.addAllowedOrigin(&quot;*&quot;);\n        cors.addAllowedHeader(&quot;*&quot;);\n        cors.addAllowedMethod(&quot;*&quot;);\n        urlBasedCorsConfigurationSource.registerCorsConfiguration(&quot;\/**&quot;, cors);\n        return new CorsFilter(urlBasedCorsConfigurationSource);\n\n    }\n}<\/code><\/pre>\n<h3>\u8fd0\u884c\uff0c\u8fd4\u56detoken<\/h3>\n<p>\u8fd0\u884c\uff0c\u8fd4\u56de\u7ed3\u679c\u4e3atoken<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1A\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<h2>SpringSecurity JSON\u767b\u5f55<\/h2>\n<p>\u8fd9\u91cc\u914d\u7f6eSpringSecurity\u4e4bJSON\u767b\u5f55<\/p>\n<p>\u8fd9\u91cc\u9700\u8981\u91cd\u5199UsernamePasswordAnthenticationFilter\u7c7b\uff0c\u4ee5\u53ca\u914d\u7f6eSpringSecurity<\/p>\n<h3>\u91cd\u5199UsernamePasswordAnthenticationFilter<\/h3>\n<pre><code class=\"scala\">public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {\n\n    @Override\n    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {\n\n        \/\/attempt Authentication when Content-Type is json\n        if(request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)\n                ||request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){\n\n            \/\/use jackson to deserialize json\n            ObjectMapper mapper = new ObjectMapper();\n            UsernamePasswordAuthenticationToken authRequest = null;\n            try (InputStream is = request.getInputStream()){\n                AuthenticationBean authenticationBean = mapper.readValue(is,AuthenticationBean.class);\n                authRequest = new UsernamePasswordAuthenticationToken(\n                        authenticationBean.getUsername(), authenticationBean.getPassword());\n            }catch (IOException e) {\n                e.printStackTrace();\n                authRequest = new UsernamePasswordAuthenticationToken(\n                        &quot;&quot;, &quot;&quot;);\n            }finally {\n                setDetails(request, authRequest);\n                return this.getAuthenticationManager().authenticate(authRequest);\n            }\n        }\n\n        \/\/transmit it to UsernamePasswordAuthenticationFilter\n        else {\n            return super.attemptAuthentication(request, response);\n        }\n    }\n}<\/code><\/pre>\n<h3>\u914d\u7f6eSecurityConfig<\/h3>\n<pre><code class=\"reasonml\">@Override\nprotected void configure(HttpSecurity http) throws Exception {\n    http\n            .cors().and()\n            .antMatcher(&quot;\/**&quot;).authorizeRequests()\n            .antMatchers(&quot;\/&quot;, &quot;\/login**&quot;).permitAll()\n            .anyRequest().authenticated()\n            \/\/\u8fd9\u91cc\u5fc5\u987b\u8981\u5199formLogin()\uff0c\u4e0d\u7136\u539f\u6709\u7684UsernamePasswordAuthenticationFilter\u4e0d\u4f1a\u51fa\u73b0\uff0c\u4e5f\u5c31\u65e0\u6cd5\u914d\u7f6e\u6211\u4eec\u91cd\u65b0\u7684UsernamePasswordAuthenticationFilter\n            .and().formLogin().loginPage(&quot;\/&quot;)\n            .and().csrf().disable();\n\n    \/\/\u7528\u91cd\u5199\u7684Filter\u66ff\u6362\u6389\u539f\u6709\u7684UsernamePasswordAuthenticationFilter\n    http.addFilterAt(customAuthenticationFilter(),\n    UsernamePasswordAuthenticationFilter.class);\n}\n\n\/\/\u6ce8\u518c\u81ea\u5b9a\u4e49\u7684UsernamePasswordAuthenticationFilter\n@Bean\nCustomAuthenticationFilter customAuthenticationFilter() throws Exception {\n    CustomAuthenticationFilter filter = new CustomAuthenticationFilter();\n    filter.setAuthenticationSuccessHandler(new SuccessHandler());\n    filter.setAuthenticationFailureHandler(new FailureHandler());\n    filter.setFilterProcessesUrl(&quot;\/login\/self&quot;);\n\n    \/\/\u8fd9\u53e5\u5f88\u5173\u952e\uff0c\u91cd\u7528WebSecurityConfigurerAdapter\u914d\u7f6e\u7684AuthenticationManager\uff0c\u4e0d\u7136\u8981\u81ea\u5df1\u7ec4\u88c5AuthenticationManager\n    filter.setAuthenticationManager(authenticationManagerBean());\n    return filter;\n}<\/code><\/pre>\n<p>\u8fd9\u6837\u5c31\u5b8c\u6210\u4f7f\u7528json\u767b\u5f55SpringSecurity<\/p>\n<h2>Spring Security \u5bc6\u7801\u52a0\u5bc6\u65b9\u5f0f<\/h2>\n<p>\u9700\u8981\u5728Config \u7c7b\u4e2d\u914d\u7f6e\u5982\u4e0b\u5185\u5bb9<\/p>\n<pre><code class=\"typescript\"> \/**\n     * \u5bc6\u7801\u52a0\u5bc6\n     *\/\n    @Bean\n    public BCryptPasswordEncoder passwordEncoder(){\n        return new BCryptPasswordEncoder();\n    }<\/code><\/pre>\n<p>\u5373\uff0c\u4f7f\u7528\u6b64\u65b9\u6cd5\uff0c\u5bf9\u5bc6\u7801\u8fdb\u884c\u52a0\u5bc6\uff0c \u5728\u4e1a\u52a1\u5c42\u7684\u65f6\u5019\uff0c\u4f7f\u7528\u6b64\u52a0\u5bc6\u7684\u65b9\u6cd5<\/p>\n<pre><code class=\"java\">@Service\n@Transactional\npublic class UserServiceImpl implements UserService {\n\n    @Resource\n    private UserRepository userRepository;\n\n    @Resource\n    private BCryptPasswordEncoder bCryptPasswordEncoder;  \/\/\u6ce8\u5165bcryct\u52a0\u5bc6\n    @Override\n    public User add(User user) {\n        user.setPassword(bCryptPasswordEncoder.encode(user.getPassword())); \/\/\u5bf9\u5bc6\u7801\u8fdb\u884c\u52a0\u5bc6\n        User user2 = userRepository.save(user);\n        return user2;\n    }\n    @Override\n    public ResultInfo login(User user) {\n        ResultInfo resultInfo=new ResultInfo();\n        User user2 = userRepository.findByName(user.getName());\n        if (user2==null) {\n            resultInfo.setCode(&quot;-1&quot;);\n            resultInfo.setMessage(&quot;\u7528\u6237\u540d\u4e0d\u5b58\u5728&quot;);\n            return resultInfo;\n        }\n\n        \/\/\u5224\u65ad\u5bc6\u7801\u662f\u5426\u6b63\u786e\n        if (!bCryptPasswordEncoder.matches(user.getPassword(),user2.getPassword())) {\n            resultInfo.setCode(&quot;-1&quot;);\n            resultInfo.setMessage(&quot;\u5bc6\u7801\u4e0d\u6b63\u786e&quot;);\n            return resultInfo;\n        }\n        resultInfo.setMessage(&quot;\u767b\u5f55\u6210\u529f&quot;);\n        return resultInfo;\n    }\n}<\/code><\/pre>\n<p>\u5373\uff0c\u4f7f\u7528BCryptPasswordEncoder \u5bf9\u5bc6\u7801\u8fdb\u884c\u52a0\u5bc6\uff0c\u4fdd\u5b58\u6570\u636e\u5e93<\/p>\n<h2>\u4f7f\u7528\u6570\u636e\u5e93\u8ba4\u8bc1<\/h2>\n<p>\u8fd9\u91cc\u4f7f\u7528\u6570\u636e\u5e93\u8ba4\u8bc1SpringSecurity<\/p>\n<h3>\u8bbe\u8ba1\u6570\u636e\u8868<\/h3>\n<p>\u8fd9\u91cc\u8bbe\u8ba1\u6570\u636e\u8868<\/p>\n<p><img decoding=\"async\" referrerpolicy=\"no-referrer\" src=\"https:\/\/segmentfault.com\/img\/bVc2I1B\" alt=\"\" title=\"\" loading=\"lazy\"><\/p>\n<h3>\u7740\u91cd\u914d\u7f6eSpringConfig<\/h3>\n<pre><code class=\"scala\">@Configurable\npublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {\n    @Autowired\n    private UserService userService;    \/\/ service \u5c42\u6ce8\u5165\n\n    @Bean\n    PasswordEncoder passwordEncoder(){\n        return new BCryptPasswordEncoder();\n    }\n\n    @Override\n    protected void configure(AuthenticationManagerBuilder auth) throws Exception {\n        \/\/ \u53c2\u6570\u4f20\u5165Service\uff0c\u8fdb\u884c\u9a8c\u8bc1\n        auth.userDetailsService(userService);\n    }\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http.authorizeRequests()\n                .antMatchers(&quot;\/admin\/**&quot;).hasRole(&quot;admin&quot;)\n                .anyRequest().authenticated()\n                .and()\n                .formLogin()\n                .loginProcessingUrl(&quot;\/login&quot;).permitAll()\n                .and()\n                .csrf().disable();\n    }\n}<\/code><\/pre>\n<p>\u8fd9\u91cc\u7740\u91cd\u914d\u7f6eSpringConfig<\/p>\n<h2>\u5c0f\u7ed3<\/h2>\n<p>\u7740\u91cd\u8bb2\u89e3\u4e86RBAC\u7684\u6743\u9650\u914d\u7f6e\uff0c\u4ee5\u53ca\u7b80\u5355\u7684\u4f7f\u7528SpringSecurity\uff0c\u4ee5\u53ca\u4f7f\u7528SpringSecurity + JWT \u5b8c\u6210\u524d\u540e\u7aef\u7684\u5206\u79bb\uff0c\u4ee5\u53ca\u914d\u7f6ejson\u767b\u5f55\uff0c\u548c\u5bc6\u7801\u52a0\u5bc6\u65b9\u5f0f\uff0c<\/p>\n<p><strong>\u8fd1\u671f\u70ed\u6587\u63a8\u8350\uff1a<\/strong><\/p>\n<p>1.<a href=\"https:\/\/link.segmentfault.com\/?enc=pvq%2B5Jo8mv1Ynt2yHUCcJA%3D%3D.2jZThVAVmy%2FxE%2BEVrZ7pJXs1VALF4UlzqfkfqpjUnHI%3D\" rel=\"nofollow\">1,000+ \u9053 Java\u9762\u8bd5\u9898\u53ca\u7b54\u6848\u6574\u7406(2022\u6700\u65b0\u7248)<\/a><\/p>\n<p>2.<a href=\"https:\/\/link.segmentfault.com\/?enc=rqJKGayZkMYNJyeHQ0eR2Q%3D%3D.zyJLSsC8NIBdWdawVMhNfAaOguVhuwWxjGecfZH13lJpGA9cV7JfGID8UYAZFcgG%2Fu0g7dAo4hwCifSbF0nVLg%3D%3D\" rel=\"nofollow\">\u52b2\u7206\uff01Java \u534f\u7a0b\u8981\u6765\u4e86\u3002\u3002\u3002<\/a><\/p>\n<p>3.<a href=\"https:\/\/link.segmentfault.com\/?enc=jbUgIjcKqp9%2FcLjtu%2BXPJg%3D%3D.oi%2By0x8j3CpduukcKXCSMyCtLt%2F1hww%2FcTR3B4m7L9aR0vlVTaafkvVOxXy%2Bgynf\" rel=\"nofollow\">Spring Boot 2.x \u6559\u7a0b\uff0c\u592a\u5168\u4e86\uff01<\/a><\/p>\n<p>4.<a href=\"https:\/\/link.segmentfault.com\/?enc=ERvloZxZ2wBlm%2BD3SBHG%2Fg%3D%3D.9iH0OeohChxqROJJO6nQW0Ev0tBNG8c5c4BXT8LsoyLpWHPcXWprqGJr29WL343cRGoeYBc4nKg3bMncmzZ4Tg%3D%3D\" rel=\"nofollow\">\u522b\u518d\u5199\u6ee1\u5c4f\u7684\u7206\u7206\u7206\u70b8\u7c7b\u4e86\uff0c\u8bd5\u8bd5\u88c5\u9970\u5668\u6a21\u5f0f\uff0c\u8fd9\u624d\u662f\u4f18\u96c5\u7684\u65b9\u5f0f\uff01\uff01<\/a><\/p>\n<p>5.<a href=\"https:\/\/link.segmentfault.com\/?enc=bhxh6ozDeClTR%2Fy5VRB1og%3D%3D.yI3MqYP9gwbvrYYhUBrd5gIgBTJqi8x%2Fp4he4zKaagJXRwXDlXPTIvvVdTAESkn1FFfB5VCxf2qw4JObgfGDAowcghQscObsGpxjdDLLHWI%3D\" rel=\"nofollow\">\u300aJava\u5f00\u53d1\u624b\u518c\uff08\u5d69\u5c71\u7248\uff09\u300b\u6700\u65b0\u53d1\u5e03\uff0c\u901f\u901f\u4e0b\u8f7d\uff01<\/a><\/p>\n<p>\u89c9\u5f97\u4e0d\u9519\uff0c\u522b\u5fd8\u4e86\u968f\u624b\u70b9\u8d5e+\u8f6c\u53d1\u54e6\uff01<\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000042556394\">https:\/\/segmentfault.com\/a\/1190000042556394<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4f5c\u8005\uff1a\u5c0f\u5c0f____\/\u6765\u6e90\uff1asegmentfault.com\/a\/1190000023052493 \u601d\u7ef4\u5bfc\u56fe\u5982\u4e0b [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[],"tags":[],"class_list":["post-10006628","post","type-post","status-publish","format-standard","hentry"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006628","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10006628"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10006628\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10006628"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10006628"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10006628"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}