{"id":1997,"date":"2021-11-14T01:03:53","date_gmt":"2021-11-13T17:03:53","guid":{"rendered":"https:\/\/199604.com\/?p=1997"},"modified":"2021-11-14T01:03:53","modified_gmt":"2021-11-13T17:03:53","slug":"shiro%e6%a1%86%e6%9e%b6%e5%bf%ab%e9%80%9f%e5%ad%a6%e4%b9%a0%e6%9c%ad%e8%ae%b0","status":"publish","type":"post","link":"https:\/\/199604.com\/1997","title":{"rendered":"Shiro\u6846\u67b6\u5feb\u901f\u5b66\u4e60\u672d\u8bb0"},"content":{"rendered":"<h2>Shiro\u6846\u67b6\u5feb\u901f\u5b66\u4e60\u672d\u8bb0<\/h2>\n<h3>\u2f00\u3001\u6743\u9650\u7684\u7ba1\u7406<\/h3>\n<h4>1.1 \u4ec0\u4e48\u662f\u6743\u9650\u7ba1\u7406<\/h4>\n<p>\u57fa\u672c\u4e0a\u6d89\u53ca\u5230\u2f64\u2f3e\u53c2\u4e0e\u7684\u7cfb\u7edf\u90fd\u8981\u8fdb\u2f8f\u6743\u9650\u7ba1\u7406\uff0c\u6743\u9650\u7ba1\u7406\u5c5e\u4e8e\u7cfb\u7edf\u5b89\u5168\u7684\u8303\u7574\uff0c\u6743\u9650\u7ba1\u7406\u5b9e\u73b0<code>\u5bf9\u2f64\u2f3e\u8bbf\u95ee\u7cfb\u7edf\u7684\u63a7\u5236<\/code>\uff0c\u6309\u7167\u5b89\u5168\u89c4\u5219\u6216\u8005<span class=\"text-highlighted-inline\" style=\"background-color: #fffd38;\">\u5b89\u5168\u7b56\u7565<\/span>\u63a7\u5236\u2f64\u2f3e\u53ef\u4ee5\u8bbf\u95ee\u2f7d\u4e14\u53ea\u80fd\u8bbf\u95ee\u2f83\u2f30\u88ab\u6388\u6743\u7684\u8d44\u6e90\u3002<\/p>\n<p>\u6743\u9650\u7ba1\u7406\u5305\u62ec\u2f64\u2f3e<code>\u2f9d\u4efd\u8ba4\u8bc1<\/code>\u548c<code>\u6388\u6743<\/code>\u4e24\u90e8\u5206\uff0c\u7b80\u79f0<code>\u8ba4\u8bc1\u6388\u6743<\/code>\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u63a7\u5236\u7684\u8d44\u6e90\u2f64\u2f3e\u2fb8\u5148\u7ecf\u8fc7\u2f9d \u4efd\u8ba4\u8bc1\uff0c\u8ba4\u8bc1\u901a\u8fc7\u540e\u2f64\u2f3e\u5177\u6709\u8be5\u8d44\u6e90\u7684\u8bbf\u95ee\u6743\u9650\u2f45\u53ef\u8bbf\u95ee\u3002<\/p>\n<h4>1.2 \u4ec0\u4e48\u662f\u2f9d\u4efd\u8ba4\u8bc1<\/h4>\n<p><code>\u2f9d\u4efd\u8ba4\u8bc1<\/code>\uff0c\u5c31\u662f\u5224\u65ad\u2f00\u4e2a\u2f64\u2f3e\u662f\u5426\u4e3a\u5408\u6cd5\u2f64\u2f3e\u7684\u5904\u7406\u8fc7\u7a0b\u3002<\/p>\n<p>\u6700\u5e38\u2f64\u7684\u7b80\u5355\u2f9d\u4efd\u8ba4\u8bc1\u2f45\u5f0f\u662f\u7cfb\u7edf\u901a\u8fc7\u6838\u5bf9\u2f64\u2f3e\u8f93\u2f0a\u7684\u2f64\u2f3e\u540d\u548c\u2f1d\u4ee4\uff0c\u770b\u5176\u662f\u5426\u4e0e\u7cfb\u7edf\u4e2d\u5b58\u50a8\u7684\u8be5\u2f64\u2f3e\u7684\u2f64\u2f3e\u540d\u548c\u2f1d\u4ee4\u2f00\u81f4\uff0c\u6765\u5224\u65ad\u2f64\u2f3e\u2f9d\u4efd\u662f\u5426\u6b63\u786e\u3002\u5bf9\u4e8e\u91c7\u2f64\u6307\u7eb9\u7b49\u7cfb\u7edf\uff0c\u5219\u51fa\u2f70\u6307\u7eb9\uff1b\u5bf9\u4e8e\u786c\u4ef6Key\u7b49\u5237\u5361\u7cfb\u7edf\uff0c\u5219\u9700\u8981\u5237\u5361\u3002<\/p>\n<h4>1.3 \u4ec0\u4e48\u662f\u6388\u6743<\/h4>\n<p><code>\u6388\u6743\uff0c\u5373\u8bbf\u95ee\u63a7\u5236<\/code>\uff0c\u63a7\u5236\u8c01\u80fd\u8bbf\u95ee\u54ea\u4e9b\u8d44\u6e90\u3002\u4e3b\u4f53\u8fdb\u2f8f\u2f9d\u4efd\u8ba4\u8bc1\u540e\u9700\u8981\u5206\u914d\u6743\u9650\u2f45\u53ef\u8bbf\u95ee\u7cfb\u7edf\u7684\u8d44\u6e90\uff0c\u5bf9\u4e8e\u67d0\u4e9b\u8d44\u6e90\u6ca1\u6709\u6743\u9650\u662f\u2f46\u6cd5\u8bbf\u95ee\u7684.<\/p>\n<h3>\u2f06\u3001\u4ec0\u4e48\u662fShiro<\/h3>\n<blockquote><p>\n  <code>Apache Shiro&amp;#x2122;<\/code> is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro\u2019s easy-to\u0002understand API, you can quickly and easily secure any application \u2012 from the smallest mobile applications to the largest web and enterprise applications.\n<\/p><\/blockquote>\n<p>Shiro \u662f\u2f00\u4e2a\u529f\u80fd\u5f3a\u2f24\u4e14\u6613\u4e8e\u4f7f\u2f64\u7684Java\u5b89\u5168\u6846\u67b6\uff0c\u5b83\u6267\u2f8f<code>\u2f9d\u4efd\u9a8c\u8bc1\u3001\u6388\u6743\u3001\u52a0\u5bc6\u548c\u4f1a\u8bdd\u7ba1\u7406<\/code>\u3002\u4f7f\u2f64 Shiro\u6613\u4e8e\u7406\u89e3\u7684API\uff0c\u60a8\u53ef\u4ee5\u5feb\u901f\u8f7b\u677e\u5730\u4fdd\u62a4\u4efb\u4f55\u5e94\u2f64\u7a0b\u5e8f\u2014\u4ece\u6700\u2f29\u7684\u79fb\u52a8\u5e94\u2f64\u7a0b\u5e8f\u5230\u6700\u2f24\u7684web\u548c \u4f01\u4e1a\u5e94\u2f64\u7a0b\u5e8f\u3002<\/p>\n<h3>\u4e09\u3001Shiro\u7684\u6838\u2f3c\u67b6\u6784<\/h3>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211104173320431.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211104173320431.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211104173320431\" \/><\/div><\/p>\n<h4>3.1 Subject<\/h4>\n<p>Subject\u5373\u4e3b\u4f53\uff0c\u5916\u90e8\u5e94\u2f64\u4e0esubject\u8fdb\u2f8f\u4ea4\u4e92\uff0csubject\u8bb0\u5f55\u4e86\u5f53\u524d\u64cd\u4f5c\u2f64\u2f3e\uff0c\u5c06\u2f64\u2f3e\u7684\u6982\u5ff5\u7406\u89e3\u4e3a\u5f53\u524d\u64cd\u4f5c\u7684\u4e3b\u4f53\uff0c\u53ef\u80fd\u662f\u2f00\u4e2a\u901a\u8fc7\u6d4f\u89c8\u5668\u8bf7\u6c42\u7684\u2f64\u2f3e\uff0c\u4e5f\u53ef\u80fd\u662f\u2f00\u4e2a\u8fd0\u2f8f\u7684\u7a0b\u5e8f\u3002<\/p>\n<p>Subject\u5728shiro\u4e2d\u662f\u2f00\u4e2a\u63a5\u2f1d\uff0c\u63a5\u2f1d\u4e2d\u5b9a\u4e49\u4e86\u5f88\u591a\u8ba4\u8bc1\u6388\u76f8\u5173\u7684\u2f45\u6cd5\uff0c\u5916\u90e8\u7a0b\u5e8f\u901a\u8fc7subject\u8fdb\u2f8f\u8ba4\u8bc1 \u6388\uff0c\u2f7dsubject\u662f\u901a\u8fc7SecurityManager\u5b89\u5168\u7ba1\u7406\u5668\u8fdb\u2f8f\u8ba4\u8bc1\u6388\u6743<\/p>\n<h4>3.2 SecurityManager<\/h4>\n<p>SecurityManager\u5373\u5b89\u5168\u7ba1\u7406\u5668\uff0c\u5bf9\u5168\u90e8\u7684subject\u8fdb\u2f8f\u5b89\u5168\u7ba1\u7406\uff0c\u5b83\u662fshiro\u7684\u6838\u2f3c\uff0c\u8d1f\u8d23\u5bf9\u6240\u6709\u7684 subject\u8fdb\u2f8f\u5b89\u5168\u7ba1\u7406\u3002\u901a\u8fc7SecurityManager\u53ef\u4ee5\u5b8c\u6210subject\u7684\u8ba4\u8bc1\u3001\u6388\u6743\u7b49\uff0c\u5b9e\u8d28\u4e0a SecurityManager\u662f\u901a\u8fc7Authenticator\u8fdb\u2f8f\u8ba4\u8bc1\uff0c\u901a\u8fc7Authorizer\u8fdb\u2f8f\u6388\u6743\uff0c\u901a\u8fc7SessionManager \u8fdb\u2f8f\u4f1a\u8bdd\u7ba1\u7406\u7b49\u3002<\/p>\n<p>SecurityManager\u662f\u2f00\u4e2a\u63a5\u2f1d\uff0c\u7ee7\u627f\u4e86Authenticator, Authorizer, SessionManager\u8fd9\u4e09\u4e2a\u63a5\u2f1d\u3002<\/p>\n<h4>3.3 Authenticator<\/h4>\n<p>Authenticator\u5373\u8ba4\u8bc1\u5668\uff0c\u5bf9\u2f64\u2f3e\u2f9d\u4efd\u8fdb\u2f8f\u8ba4\u8bc1\uff0cAuthenticator\u662f\u2f00\u4e2a\u63a5\u2f1d\uff0cshiro\u63d0\u4f9b ModularRealmAuthenticator\u5b9e\u73b0\u7c7b\uff0c\u901a\u8fc7ModularRealmAuthenticator\u57fa\u672c\u4e0a\u53ef\u4ee5\u6ee1\u2f9c\u2f24\u591a\u6570\u9700 \u6c42\uff0c\u4e5f\u53ef\u4ee5\u2f83\u5b9a\u4e49\u8ba4\u8bc1\u5668\u3002<\/p>\n<h4>3.4 Authorizer<\/h4>\n<p>Authorizer\u5373\u6388\u6743\u5668\uff0c\u2f64\u2f3e\u901a\u8fc7\u8ba4\u8bc1\u5668\u8ba4\u8bc1\u901a\u8fc7\uff0c\u5728\u8bbf\u95ee\u529f\u80fd\u65f6\u9700\u8981\u901a\u8fc7\u6388\u6743\u5668\u5224\u65ad\u2f64\u2f3e\u662f\u5426\u6709\u6b64\u529f \u80fd\u7684\u64cd\u4f5c\u6743\u9650\u3002<\/p>\n<h4>3.5 Realm<\/h4>\n<p>Realm\u5373\u9886\u57df\uff0c\u76f8\u5f53\u4e8edatasource\u6570\u636e\u6e90\uff0csecurityManager\u8fdb\u2f8f\u5b89\u5168\u8ba4\u8bc1\u9700\u8981\u901a\u8fc7Realm\u83b7\u53d6\u2f64\u2f3e \u6743\u9650\u6570\u636e\uff0c\u2f50\u5982\uff1a\u5982\u679c\u2f64\u2f3e\u2f9d\u4efd\u6570\u636e\u5728\u6570\u636e\u5e93\u90a3\u4e48realm\u5c31\u9700\u8981\u4ece\u6570\u636e\u5e93\u83b7\u53d6\u2f64\u2f3e\u2f9d\u4efd\u4fe1\u606f\u3002<\/p>\n<blockquote><p>\n  \u6ce8\u610f\uff1a\u4e0d\u8981\u628arealm\u7406\u89e3\u6210\u53ea\u662f\u4ece\u6570\u636e\u6e90\u53d6\u6570\u636e\uff0c\u5728realm\u4e2d\u8fd8\u6709\u8ba4\u8bc1\u6388\u6743\u6821\u9a8c\u7684\u76f8\u5173\u7684\u4ee3\u7801\u3002\n<\/p><\/blockquote>\n<h4>3.6 SessionManager<\/h4>\n<p>sessionManager\u5373\u4f1a\u8bdd\u7ba1\u7406\uff0cshiro\u6846\u67b6\u5b9a\u4e49\u4e86\u2f00\u5957\u4f1a\u8bdd\u7ba1\u7406\uff0c\u5b83\u4e0d\u4f9d\u8d56web\u5bb9\u5668\u7684session\uff0c\u6240\u4ee5 shiro\u53ef\u4ee5\u4f7f\u2f64\u5728\u2faeweb\u5e94\u2f64\u4e0a\uff0c\u4e5f\u53ef\u4ee5\u5c06\u5206\u5e03\u5f0f\u5e94\u2f64\u7684\u4f1a\u8bdd\u96c6\u4e2d\u5728\u2f00\u70b9\u7ba1\u7406\uff0c\u6b64\u7279\u6027\u53ef\u4f7f\u5b83\u5b9e\u73b0\u5355\u70b9\u767b\u5f55\u3002<\/p>\n<h4>3.7 SessionDAO<\/h4>\n<p>SessionDAO\u5373\u4f1a\u8bdddao\uff0c\u662f\u5bf9session\u4f1a\u8bdd\u64cd\u4f5c\u7684\u2f00\u5957\u63a5\u2f1d\uff0c\u2f50\u5982\u8981\u5c06session\u5b58\u50a8\u5230\u6570\u636e\u5e93\uff0c\u53ef\u4ee5\u901a \u8fc7jdbc\u5c06\u4f1a\u8bdd\u5b58\u50a8\u5230\u6570\u636e\u5e93\u3002<\/p>\n<h4>3.8 CacheManager<\/h4>\n<p>CacheManager\u5373\u7f13\u5b58\u7ba1\u7406\uff0c\u5c06\u2f64\u2f3e\u6743\u9650\u6570\u636e\u5b58\u50a8\u5728\u7f13\u5b58\uff0c\u8fd9\u6837\u53ef\u4ee5\u63d0\u2fbc\u6027\u80fd\u3002<\/p>\n<h4>3.9 Cryptography<\/h4>\n<p>Cryptography\u5373\u5bc6\u7801\u7ba1\u7406\uff0cshiro\u63d0\u4f9b\u4e86\u2f00\u5957\u52a0\u5bc6\/\u89e3\u5bc6\u7684\u7ec4\u4ef6\uff0c\u2f45\u4fbf\u5f00\u53d1\u3002\u2f50\u5982\u63d0\u4f9b\u5e38\u2f64\u7684\u6563\u5217\u3001\u52a0\/ \u89e3\u5bc6\u7b49\u529f\u80fd\u3002<\/p>\n<h3>\u56db\u3001Shiro\u4e2d\u7684\u8ba4\u8bc1<\/h3>\n<h4>4.1 \u8ba4\u8bc1<\/h4>\n<p>\u2f9d\u4efd\u8ba4\u8bc1\uff0c\u5c31\u662f\u5224\u65ad\u2f00\u4e2a\u2f64\u2f3e\u662f\u5426\u4e3a\u5408\u6cd5\u2f64\u2f3e\u7684\u5904\u7406\u8fc7\u7a0b\u3002\u6700\u5e38\u2f64\u7684\u7b80\u5355\u2f9d\u4efd\u8ba4\u8bc1\u2f45\u5f0f\u662f\u7cfb\u7edf\u901a\u8fc7\u6838 \u5bf9\u2f64\u2f3e\u8f93\u2f0a\u7684\u2f64\u2f3e\u540d\u548c\u2f1d\u4ee4\uff0c\u770b\u5176\u662f\u5426\u4e0e\u7cfb\u7edf\u4e2d\u5b58\u50a8\u7684\u8be5\u2f64\u2f3e\u7684\u2f64\u2f3e\u540d\u548c\u2f1d\u4ee4\u2f00\u81f4\uff0c\u6765\u5224\u65ad\u2f64\u2f3e\u2f9d\u4efd \u662f\u5426\u6b63\u786e\u3002<\/p>\n<h4>4.2 Shiro\u4e2d\u8ba4\u8bc1\u7684\u5173\u952e\u5bf9\u8c61<\/h4>\n<ol>\n<li>Subject\uff1a\u4e3b\u4f53<\/li>\n<\/ol>\n<p>\u8bbf\u95ee\u7cfb\u7edf\u7684\u2f64\u2f3e\uff0c\u4e3b\u4f53\u53ef\u4ee5\u662f\u2f64\u2f3e\u3001\u7a0b\u5e8f\u7b49\uff0c\u8fdb\u2f8f\u8ba4\u8bc1\u7684\u90fd\u79f0\u4e3a\u4e3b\u4f53\uff1b<\/p>\n<ol start=\"2\">\n<li>Principal\uff1a\u2f9d\u4efd\u4fe1\u606f<\/li>\n<\/ol>\n<p>\u662f\u4e3b\u4f53\uff08subject\uff09\u8fdb\u2f8f\u2f9d\u4efd\u8ba4\u8bc1\u7684\u6807\u8bc6\uff0c\u6807\u8bc6\u5fc5\u987b\u5177\u6709\u552f\u2f00\u6027\uff0c\u5982\u2f64\u2f3e\u540d\u3001\u2f3f\u673a\u53f7\u3001\u90ae\u7bb1\u5730\u5740\u7b49\uff0c\u2f00 \u4e2a\u4e3b\u4f53\u53ef\u4ee5\u6709\u591a\u4e2a\u2f9d\u4efd\uff0c\u4f46\u662f\u5fc5\u987b\u6709\u2f00\u4e2a\u4e3b\u2f9d\u4efd\uff08Primary Principal\uff09\u3002<\/p>\n<ol start=\"3\">\n<li>credential\uff1a\u51ed\u8bc1\u4fe1\u606f<\/li>\n<\/ol>\n<p>\u662f\u53ea\u6709\u4e3b\u4f53\u2f83\u2f30\u77e5\u9053\u7684\u5b89\u5168\u4fe1\u606f\uff0c\u5982\u5bc6\u7801\u3001\u8bc1\u4e66\u7b49\u3002<\/p>\n<h4>4.3 \u8ba4\u8bc1\u6d41\u7a0b<\/h4>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211104230400748.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211104230400748.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211104230400748\" \/><\/div><\/p>\n<h4>4.4 \u8ba4\u8bc1\u7684\u5f00\u53d1<\/h4>\n<p>1.\u521b\u5efa\u9879\u76ee\u5e76\u5f15\u7528\u4f9d\u8d56<\/p>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;dependency&gt;\n    &lt;groupId&gt;org.apache.shiro&lt;\/groupId&gt;\n    &lt;artifactId&gt;shiro-core&lt;\/artifactId&gt;\n    &lt;version&gt;1.5.3&lt;\/version&gt;\n&lt;\/dependency&gt;\n<\/code><\/pre>\n<p>2.\u521d\u6b21\u5b66\u4e60,\u5728resources\u65b0\u589e\u4e00\u4e2ashiro.ini\u914d\u7f6e\u6587\u4ef6<\/p>\n<pre><code class=\"language-ini line-numbers\">[users]\nglj=123456\n<\/code><\/pre>\n<p>3.\u5177\u4f53\u4f8b\u5b50<\/p>\n<pre><code class=\"language-java line-numbers\">public class AuthenticatorTest {\n    public static void main(String[] args) {\n        \/\/ 1.\u521b\u5efa\u5b89\u5168\u7ba1\u7406\u5668\n        DefaultSecurityManager securityManager = new DefaultSecurityManager();\n\n        \/\/ 2.\u7ed9\u5b89\u5168\u7ba1\u7406\u5668\u8bbe\u7f6erealm\n        securityManager.setRealm(new IniRealm(\"classpath:shiro.ini\"));\n\n        \/\/ 3.SecurityUtils\u7ed9\u5168\u5c40\u2f2f\u5177\u7c7b\u8bbe\u7f6e\u5b89\u5168\u7ba1\u7406\u5668\n        SecurityUtils.setSecurityManager(securityManager);\n\n        \/\/ 4.\u5173\u952e\u5bf9\u8c61subject\u4e3b\u4f53\n        Subject subject = SecurityUtils.getSubject();\n\n        \/\/ 5.\u521b\u5efa\u4ee4\u724c\n        UsernamePasswordToken token = new UsernamePasswordToken(\"glj\", \"123456\");\n\n        \/\/ \u7528\u6237\u767b\u5f55\n        try {\n            System.out.println(\"\u8ba4\u8bc1\u72b6\u6001:\"+subject.isAuthenticated());\n            subject.login(token);\n            System.out.println(\"\u8ba4\u8bc1\u72b6\u6001:\"+subject.isAuthenticated());\n            if (subject.isAuthenticated()) {\n                System.out.println(\"\u8ba4\u8bc1\u6210...\");\n            }\n        } catch (UnknownAccountException e) {\n            System.out.println(\"\u8ba4\u8bc1\u5931\u8d25:\u7528\u6237\u540d\u4e0d\u5b58\u5728~\");\n        } catch (IncorrectCredentialsException e){\n            System.out.println(\"\u8ba4\u8bc1\u5931\u8d25:\u5bc6\u7801\u9519\u8bef~\");\n        }\n    }\n}\n<\/code><\/pre>\n<h4>4.5\u9605\u8bfb\u6e90\u7801\u8fc7\u7a0b:<\/h4>\n<p>\u6e90\u7801\u5173\u952e->\u2f64\u2f3e\u540d\u6821\u9a8c<\/p>\n<p><code>org.apache.shiro.realm.SimpleAccountRealm ##doGetAuthenticationInfo<\/code>\u83b7\u53d6\u7528\u6237\u8d26\u53f7\u4fe1\u606f~<\/p>\n<pre><code class=\"language-java line-numbers\">protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {\n    UsernamePasswordToken upToken = (UsernamePasswordToken)token;\n    SimpleAccount account = this.getUser(upToken.getUsername());\n    if (account != null) {\n        if (account.isLocked()) {\n            throw new LockedAccountException(\"Account [\" + account + \"] is locked.\");\n        }\n\n        if (account.isCredentialsExpired()) {\n            String msg = \"The credentials for account [\" + account + \"] are expired\";\n            throw new ExpiredCredentialsException(msg);\n        }\n    }\n\n    return account;\n}\n<\/code><\/pre>\n<p>\u6e90\u7801\u5173\u952e->\u5bc6\u7801\u6821\u9a8c<\/p>\n<p><code>org.apache.shiro.realm.AuthenticatingRealm ##assertCredentialsMatch<\/code> \u5bc6\u7801\u7684\u6821\u9a8c<\/p>\n<pre><code class=\"language-java line-numbers\">protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {\n    CredentialsMatcher cm = this.getCredentialsMatcher();\n    if (cm != null) {\n        if (!cm.doCredentialsMatch(token, info)) {\n            String msg = \"Submitted credentials for token [\" + token + \"] did not match the expected credentials.\";\n            throw new IncorrectCredentialsException(msg);\n        }\n    } else {\n        throw new AuthenticationException(\"A CredentialsMatcher must be configured in order to verify credentials during authentication.  If you do not wish for credentials to be examined, you can configure an \" + AllowAllCredentialsMatcher.class.getName() + \" instance.\");\n    }\n}\n<\/code><\/pre>\n<p>\u60f3\u6cd5\uff1a\u662f\u4e0d\u662f\u628a\u67e5\u2f64\u2f3e\u540d\u90e8\u5206\u7684\u5b9e\u73b0\u66ff\u6362\u6210\u2f83\u2f30\u7684\uff0c\u4ece\u6570\u636e\u5e93\u4e2d\u67e5\u627e\u5462\uff1f<code>org.apache.shiro.realm.AuthorizingRealm<\/code><\/p>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211105000954492.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211105000954492.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211105000954492\" \/><\/div><\/p>\n<p>\u6839\u636e\u8ba4\u8bc1\u6e90\u7801\u4f7f\u7528\u7684\u662f<code>SimpleAccountRealm<\/code><\/p>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211105001043201.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211105001043201.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211105001043201\" \/><\/div><\/p>\n<p>\u2f6c\u524d\u8fd9\u4e2aSimpleAccountRealm\u7ee7\u627f\u4e86AuthorizingRealm\uff0c\u91cd\u5199\u4e86\u8ba4\u8bc1\u548c\u6388\u6743\u2f45\u6cd5\u3002<\/p>\n<h4>4.6 \u6e90\u7801\u603b\u7ed3<\/h4>\n<h5>1. AuthenticatingRealm \u662f\u8ba4\u8bc1realm\uff0c <code>org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo<\/code><\/h5>\n<h5>2.AuthenticatingRealm\u662f\u6388\u6743realm\uff0c <code>org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo<\/code><\/h5>\n<h4>4.7\u2f83\u5b9a\u4e49realm<\/h4>\n<p>\u65b0\u5efa\u81ea\u5b9a\u4e49\u7684realm<\/p>\n<pre><code class=\"language-java line-numbers\">public class CustomerRealm extends AuthorizingRealm {\n\n    \/**\n     * \u6388\u6743\n     * @param principals\n     * @return\n     *\/\n    @Override\n    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {\n        return null;\n    }\n\n    \/**\n     * \u8ba4\u8bc1\n     * @param token\n     * @return\n     * @throws AuthenticationException\n     *\/\n    @Override\n    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {\n        \/\/ \u83b7\u53d6token\u7528\u6237\u540d\n        String principal = (String) token.getPrincipal();\n        System.out.println(\"principal:\"+principal);\n\n        if (\"glj\".equals(principal)) {\n            \/\/ \u53c2\u65701:\u8fd4\u56de\u6570\u636e\u5e93\u8d26\u53f7\n            \/\/ \u53c2\u65702:\u8fd4\u56de\u6570\u636e\u5e93\u5bc6\u7801\n            \/\/ \u53c2\u65703:\u5f53\u524drealm\u540d\u79f0\n            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(principal, \"123456\", this.getName());\n            return authenticationInfo;\n\n        }\n\n        return null;\n    }\n}\n<\/code><\/pre>\n<p>\u6d4b\u8bd5\u4f8b\u5b50:<\/p>\n<pre><code class=\"language-java line-numbers\">public class CustomerRealmAuthenticatorTest {\n\n    public static void main(String[] args) {\n        \/\/ 1.\u521b\u5efa\u5b89\u5168\u7ba1\u7406\u5668\n        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();\n        \/\/ 2.\u7ed9\u5b89\u5168\u7ba1\u7406\u5668\u8bbe\u7f6erealm\n        defaultSecurityManager.setRealm(new CustomerRealm());\n        \/\/ 3.SecurityUtils\u7ed9\u5168\u5c40\u2f2f\u5177\u7c7b\u8bbe\u7f6e\u5b89\u5168\u7ba1\u7406\u5668\n        SecurityUtils.setSecurityManager(defaultSecurityManager);\n        \/\/ 4.\u5173\u952e\u5bf9\u8c61subject\u4e3b\u4f53\n        Subject subject = SecurityUtils.getSubject();\n        \/\/ 5.\u521b\u5efa\u4ee4\u724c\n        UsernamePasswordToken token = new UsernamePasswordToken(\"glj\", \"123456\");\n\n        try {\n            subject.login(token);\n        } catch (IncorrectCredentialsException exception){\n            System.out.println(\"\u5bc6\u7801\u9519\u8bef\");\n        }\n    }\n}\n<\/code><\/pre>\n<p>\u62d3\u5c55\u7684\u7c7b\u56fe<code>SimpleAuthenticationInfo<\/code>:<\/p>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211108150138389.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211108150138389.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211108150138389\" \/><\/div><\/p>\n<h4>4.8\u4f7f\u2f64MD5\u548csalt<\/h4>\n<h5>MD5\u65b9\u6cd5\u7684\u4f7f\u7528\u89e3\u91ca:<\/h5>\n<pre><code class=\"language-java line-numbers\">public class ShiroMD5Test {\n\n    public static void main(String[] args) {\n        \/\/1.\u4e0d\u63a8\u8350\u7684\u2f64\u6cd5\n        Md5Hash md5Hash = new Md5Hash();\n        md5Hash.setBytes(\"123456\".getBytes(StandardCharsets.UTF_8));\n        String toHex = md5Hash.toHex();\n        System.out.println(\"toHex:\"+toHex);\n        \/\/ 313233343536\n\n        \/\/ \u4f7f\u7528md5\n        Md5Hash md5 = new Md5Hash(\"123456\");\n        System.out.println(\"hash:\"+md5.toHex());\n\n        \/\/ \u4f7f\u7528md5+salt\n        Md5Hash md5Salt = new Md5Hash(\"123456\", \"glj\");\n        System.out.println(\"md5_salt:\"+md5Salt.toHex());\n\n        \/\/\u4f7f\u7528mdt+salt+hash\u6563\u5217(\u9700\u8981md5 \u591a\u5c11\u6b21)\n        Md5Hash md5SaltHash = new Md5Hash(\"123456\", \"glj\", 1024);\n        System.out.println(\"md5_salt_hash:\"+md5SaltHash.toHex());\n    }\n\n}\n<\/code><\/pre>\n<h5>\u4f7f\u2f64MD5+salt+\u6563\u5217\u7684\u4f8b\u5b50:<\/h5>\n<pre><code class=\"language-java line-numbers\">public class CustomerMD5Realm extends AuthorizingRealm {\n\n\n    @Override\n    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {\n        return null;\n    }\n\n    @Override\n    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {\n        String principal = (String) authenticationToken.getPrincipal();\n\n        if (\"glj\".equals(principal)) {\n            \/\/ \u53c2\u65701:\u8fd4\u56de\u6570\u636e\u5e93\u8d26\u53f7\n            \/\/ \u53c2\u65702:\u8fd4\u56de\u6570\u636e\u5e93\u5bc6\u7801\n            \/\/ \u53c2\u65703:\u6ce8\u518c\u65f6\u7684\u968f\u673a\u76d0\n            \/\/ \u53c2\u65704:\u5f53\u524drealm\u540d\u79f0\n            SimpleAuthenticationInfo authenticationInfo =\n                    new SimpleAuthenticationInfo(principal,\n                    \"cb99784c218fecedb3d592b5b37e6ba3\",\n                    ByteSource.Util.bytes(\"glj\"),\n                    this.getName());\n            return authenticationInfo;\n\n        }\n\n        return null;\n    }\n}\n<\/code><\/pre>\n<pre><code class=\"language-java line-numbers\">package com.glj;\n\nimport com.glj.realm.CustomerMD5Realm;\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.authc.AuthenticationException;\nimport org.apache.shiro.authc.UsernamePasswordToken;\nimport org.apache.shiro.authc.credential.HashedCredentialsMatcher;\nimport org.apache.shiro.mgt.DefaultSecurityManager;\nimport org.apache.shiro.subject.Subject;\n\n\/**\n * @author: GuoLiangJun\n * @date: Created in 2021\/11\/8 15:37\n * Description:\n * Created with IntelliJ IDEA.\n *\/\npublic class CustomerMD5RealmAuthenticatorTest {\n\n     public static void main(String[] args) {\n\n         \/\/ 1.\u521b\u5efa\u5b89\u5168\u7ba1\u7406\u5668\n         DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();\n\n         \/\/ 2. \u7ed9\u5b89\u5168\u7ba1\u7406\u5668\u8bbe\u7f6erealm\n         CustomerMD5Realm realm = new CustomerMD5Realm();\n         \/\/ 2.1 \u8bbe\u7f6erealm\u4f7f\u7528hash\u51ed\u8bc1\u5668\n         HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();\n         \/\/ 2.2 \u8bbe\u7f6e\u4f7f\u2f64\u5bc6\u7801\u52a0\u5bc6\u7b97\u6cd5\n         credentialsMatcher.setHashAlgorithmName(\"md5\");\n         \/\/ 2.3 \u8bbe\u7f6e\u6563\u5217\u6b21\u6570(\u5982\u679c\u662fmd5+salt+hash1024)\n         credentialsMatcher.setHashIterations(1024);\n\n         realm.setCredentialsMatcher(credentialsMatcher);\n         defaultSecurityManager.setRealm(realm);\n\n         \/\/ 3.SecurityUtils\u7ed9\u5168\u5c40\u2f2f\u5177\u7c7b\u8bbe\u7f6e\u5b89\u5168\u7ba1\u7406\u5668\n         SecurityUtils.setSecurityManager(defaultSecurityManager);\n         \/\/ 4.\u5173\u952e\u5bf9\u8c61subject\u4e3b\u4f53\n         Subject subject = SecurityUtils.getSubject();\n         \/\/ 5.\u521b\u5efa\u4ee4\u724c\n         UsernamePasswordToken token = new UsernamePasswordToken(\"glj\", \"123456\");\n\n         try {\n             subject.login(token);\n             System.out.println(\"\u767b\u5f55\u6210\u529f\");\n         } catch (AuthenticationException e) {\n             e.printStackTrace();\n         }\n\n     }\n\n}\n\n<\/code><\/pre>\n<p><code>HashedCredentialsMatcher<\/code>\u62d3\u5c55\u7c7b\u56fe:<\/p>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211108160449851.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211108160449851.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211108160449851\" \/><\/div><\/p>\n<h3>\u4e94\u3001Shiro\u4e2d\u7684\u6388\u6743<\/h3>\n<h4>5.1 \u6388\u6743<\/h4>\n<p>\u6388\u6743\uff0c\u5373\u8bbf\u95ee\u63a7\u5236\uff0c\u63a7\u5236\u8c01\u80fd\u8bbf\u95ee\u54ea\u4e9b\u8d44\u6e90\u3002\u4e3b\u4f53\u8fdb\u2f8f\u2f9d\u4efd\u8ba4\u8bc1\u540e\u9700\u8981\u5206\u914d\u6743\u9650\u2f45\u53ef\u8bbf\u95ee\u7cfb\u7edf\u7684\u8d44 \u6e90\uff0c\u5bf9\u4e8e\u67d0\u4e9b\u8d44\u6e90\u6ca1\u6709\u6743\u9650\u662f\u2f46\u6cd5\u8bbf\u95ee\u7684\u3002<\/p>\n<h4>5.2 \u5173\u952e\u5bf9\u8c61<\/h4>\n<p><strong>\u6388\u6743\u53ef\u7b80\u5355\u7406\u89e3\u4e3awho\u5bf9what(which)\u8fdb\u2f8fHow\u64cd\u4f5c<\/strong>\uff1a<\/p>\n<ol>\n<li><strong>Who\uff0c\u5373\u4e3b\u4f53\uff08Subject\uff09<\/strong>\uff0c\u4e3b\u4f53\u9700\u8981\u8bbf\u95ee\u7cfb\u7edf\u4e2d\u7684\u8d44\u6e90\u3002<\/li>\n<li><strong>What\uff0c\u5373\u8d44\u6e90\uff08Resource)<\/strong>\uff0c\u5982\u7cfb\u7edf\u83dc\u5355\u3001\u2eda\u2faf\u3001\u6309\u94ae\u3001\u7c7b\u2f45\u6cd5\u3001\u7cfb\u7edf\u5546\u54c1\u4fe1\u606f\u7b49\u3002\u8d44\u6e90\u5305\u62ec<code>\u8d44\u6e90\u7c7b\u578b<\/code>\u548c<code>\u8d44\u6e90\u5b9e\u4f8b<\/code>\uff0c\u2f50\u5982\u5546\u54c1\u4fe1\u606f\u4e3a\u8d44\u6e90\u7c7b\u578b\uff0c\u7c7b\u578b\u4e3at01\u7684\u5546\u54c1\u4e3a\u8d44\u6e90\u5b9e\u4f8b\uff0c\u7f16\u53f7\u4e3a001\u7684\u5546\u54c1\u4fe1\u606f\u4e5f\u5c5e\u4e8e\u8d44\u6e90\u5b9e\u4f8b\u3002<\/li>\n<li><strong>How\uff0c\u6743\u9650\/\u8bb8\u53ef\uff08Permission)<\/strong>&#8211;CRUD\uff0c\u89c4\u5b9a\u4e86\u4e3b\u4f53\u5bf9\u8d44\u6e90\u7684\u64cd\u4f5c\u8bb8\u53ef\uff0c\u6743\u9650\u79bb\u5f00\u8d44\u6e90\u6ca1\u6709\u610f\u4e49\uff0c\u5982\u2f64\u2f3e <code>\u67e5\u8be2\u6743\u9650\u3001\u2f64\u2f3e\u6dfb\u52a0\u6743\u9650\u3001\u67d0\u4e2a\u7c7b\u2f45\u6cd5\u7684\u8c03\u2f64\u6743\u9650\u3001\u7f16\u53f7\u4e3a001\u2f64\u2f3e\u7684\u4fee\u6539\u6743\u9650<\/code>\u7b49\uff0c\u901a\u8fc7\u6743\u9650\u53ef\u77e5\u4e3b\u4f53\u5bf9\u54ea\u4e9b\u8d44\u6e90\u90fd\u6709\u54ea\u4e9b\u64cd\u4f5c\u8bb8\u53ef\u3002<\/li>\n<\/ol>\n<h4>5.3 \u6388\u6743\u6d41\u7a0b<\/h4>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/2776d1da95d468069505ec23d87fe23e.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/2776d1da95d468069505ec23d87fe23e.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"img\" \/><\/div><\/p>\n<h4>5.4 \u6388\u6743\u65b9\u5f0f<\/h4>\n<p><strong>\u57fa\u4e8e\u89d2\u8272\u7684\u8bbf\u95ee\u63a7\u5236<\/strong><\/p>\n<ul>\n<li>RBAC\u57fa\u4e8e\u89d2\u8272\u7684\u8bbf\u95ee\u63a7\u5236\uff08Role-Based Access Control\uff09\u662f\u4ee5\u89d2\u8272\u4e3a\u4e2d\u5fc3\u8fdb\u884c\u8bbf\u95ee\u63a7\u5236<\/li>\n<\/ul>\n<pre><code class=\"language-java line-numbers\">if(subject.hasRole(\"admin\")){\n   \/\/admin\u64cd\u4f5c\u54ea\u4e9b\u8d44\u6e90\n}\n<\/code><\/pre>\n<p><strong>\u57fa\u4e8e\u8d44\u6e90\u7684\u8bbf\u95ee\u63a7\u5236<\/strong><\/p>\n<ul>\n<li>RBAC\u57fa\u4e8e\u8d44\u6e90\u7684\u8bbf\u95ee\u63a7\u5236\uff08Resource-Based Access Control\uff09\u662f\u4ee5\u8d44\u6e90\u4e3a\u4e2d\u5fc3\u8fdb\u884c\u8bbf\u95ee\u63a7\u5236<\/li>\n<\/ul>\n<pre><code class=\"language-java line-numbers\">if (subject.isPermission(\"user:find:*\")) {\/\/\u6b64\u7528\u6237\u5bf9user\u6a21\u5757\u4e0b\u6240\u6709\u8d44\u6e90\u6709\u67e5\u627e\u6743\u9650\n    \/\/ \u6a21\u5757.\u6743\u9650.\u8d44\u6e90\n    user:update:01 \uff08\u8d44\u6e90\u5b9e\u4f8b\uff09\u5bf901\u53f7\u2f64\u2f3e\u5177\u6709\u66f4\u65b0\u6743\u9650\n    user:*:01 01\u53f7\u2f64\u2f3e\u5177\u6709\u6743\u9650\n}\nif (subject.isPermission(\"user:update:01\")) {\n    \/\/ \uff08\u8d44\u6e90\u5b9e\u4f8b\uff09\u5bf901\u53f7\u2f64\u2f3e\u5177\u6709\u4fee\u6539\u6743\u9650\n}\nif (subject.isPermission(\"user:update:*\")) {\n    \/\/ \uff08\u8d44\u6e90\u7c7b\u578b\uff09\u5bf901\u53f7\u2f64\u2f3e\u5177\u6709\u4fee\u6539\u6743\u9650\n}\n\n<\/code><\/pre>\n<h4>5.5 \u6743\u9650\u5b57\u7b26\u4e32<\/h4>\n<p>\u6743\u9650\u5b57\u7b26\u4e32\u7684\u89c4\u5219\u662f\uff1a<strong>\u8d44\u6e90\u6807\u8bc6\u7b26\uff1a\u64cd\u4f5c\uff1a\u8d44\u6e90\u5b9e\u4f8b\u6807\u8bc6\u7b26<\/strong>\uff0c\u610f\u601d\u662f\u5bf9\u54ea\u4e2a\u8d44\u6e90\u7684\u54ea\u4e2a\u5b9e\u4f8b\u5177\u6709\u4ec0\u4e48\u64cd\u4f5c\uff0c\u201c:\u201d\u662f\u8d44\u6e90\/\u64cd\u4f5c\/\u5b9e\u4f8b\u7684\u5206\u5272\u7b26\uff0c\u6743\u9650\u5b57\u7b26\u4e32\u4e5f\u53ef\u4ee5\u4f7f\u7528*\u901a\u914d\u7b26\u3002<\/p>\n<p>\u4f8b\u5b50\uff1a<\/p>\n<ul>\n<li>\u7528\u6237\u521b\u5efa\u6743\u9650\uff1auser:create\uff0c\u6216user:create:*<\/li>\n<li>\u7528\u6237\u4fee\u6539\u5b9e\u4f8b001\u7684\u6743\u9650\uff1auser:update:001<\/li>\n<li>\u7528\u6237\u5b9e\u4f8b001\u7684\u6240\u6709\u6743\u9650\uff1auser:*\uff1a001<\/li>\n<\/ul>\n<h4>5.6 Shiro\u4e2d\u6388\u6743\u7f16\u7a0b\u5b9e\u73b0\u65b9\u5f0f<\/h4>\n<ul>\n<li><strong>\u7f16\u7a0b\u5f0f<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-java line-numbers\">Subject subject = SecurityUtils.getSubject();\nif(subject.hasRole(\u201cadmin\u201d)) {\n    \/\/\u6709\u6743\u9650\n} else {\n    \/\/\u65e0\u6743\u9650\n}\n<\/code><\/pre>\n<ul>\n<li><strong>\u6ce8\u89e3\u5f0f<\/strong><\/li>\n<\/ul>\n<pre><code class=\"language-java line-numbers\">@RequiresRoles(\"admin\")\npublic String helloShiro() {\n    \/\/\u6709\u6743\u9650\n}\n<\/code><\/pre>\n<ul>\n<li><strong>\u6807\u7b7e\u5f0f<\/strong>(Jsp\u9875\u9762\u4f7f\u7528\u7684..)<\/li>\n<\/ul>\n<pre><code class=\"language-java line-numbers\">&lt;shiro:hasRole name=\"admin\"&gt;\n    &lt;!\u2014 \u6709\u6743\u9650\u2014&gt;\n&lt;\/shiro:hasRole&gt;\n<\/code><\/pre>\n<p>\u5b8c\u6574\u4f8b\u5b50():<\/p>\n<p>CustomerMD5Realm<\/p>\n<pre><code class=\"language-java line-numbers\">public class CustomerMD5Realm extends AuthorizingRealm {\n\n\n    \/**\n     * \u6388\u6743\n     * @param principalCollection\n     * @return\n     *\/\n    @Override\n    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {\n        String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();\n        System.out.println(\"----&gt;\"+primaryPrincipal+\",\u53c8\u6765\u8bf7\u6c42\u62c9&lt;----\");\n        if (\"glj\".equals(primaryPrincipal)) {\n            HashSet&lt;String&gt; set = new HashSet&lt;&gt;();\n            set.add(\"admin\");\n            set.add(\"users\");\n            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(set);\n            simpleAuthorizationInfo.addRole(\"super\");\n            simpleAuthorizationInfo.addStringPermission(\"user:*:*\");\n            return simpleAuthorizationInfo;\n        }\n        return null;\n    }\n\n    \/**\n     * \u8ba4\u8bc1\n     * @param authenticationToken\n     * @return\n     * @throws AuthenticationException\n     *\/\n    @Override\n    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {\n        String principal = (String) authenticationToken.getPrincipal();\n\n        if (\"glj\".equals(principal)) {\n            \/\/ \u53c2\u65701:\u8fd4\u56de\u6570\u636e\u5e93\u8d26\u53f7\n            \/\/ \u53c2\u65702:\u8fd4\u56de\u6570\u636e\u5e93\u5bc6\u7801\n            \/\/ \u53c2\u65703:\u6ce8\u518c\u65f6\u7684\u968f\u673a\u76d0\n            \/\/ \u53c2\u65704:\u5f53\u524drealm\u540d\u79f0\n            SimpleAuthenticationInfo authenticationInfo =\n                    new SimpleAuthenticationInfo(principal,\n                    \"cb99784c218fecedb3d592b5b37e6ba3\",\n                    ByteSource.Util.bytes(\"glj\"),\n                    this.getName());\n            return authenticationInfo;\n\n        }\n\n        return null;\n    }\n}\n<\/code><\/pre>\n<p>CustomerMD5RealmAuthenticatorTest<\/p>\n<pre><code class=\"language-java line-numbers\">public class CustomerMD5RealmAuthenticatorTest {\n\n     public static void main(String[] args) {\n\n         \/\/ 1.\u521b\u5efa\u5b89\u5168\u7ba1\u7406\u5668\n         DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();\n\n         \/\/ 2. \u7ed9\u5b89\u5168\u7ba1\u7406\u5668\u8bbe\u7f6erealm\n         CustomerMD5Realm realm = new CustomerMD5Realm();\n         \/\/ 2.1 \u8bbe\u7f6erealm\u4f7f\u7528hash\u51ed\u8bc1\u5668\n         HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();\n         \/\/ 2.2 \u8bbe\u7f6e\u4f7f\u2f64\u5bc6\u7801\u52a0\u5bc6\u7b97\u6cd5\n         credentialsMatcher.setHashAlgorithmName(\"md5\");\n         \/\/ 2.3 \u8bbe\u7f6e\u6563\u5217\u6b21\u6570(\u5982\u679c\u662fmd5+salt+hash1024)\n         credentialsMatcher.setHashIterations(1024);\n\n         realm.setCredentialsMatcher(credentialsMatcher);\n         defaultSecurityManager.setRealm(realm);\n\n         \/\/ 3.SecurityUtils\u7ed9\u5168\u5c40\u2f2f\u5177\u7c7b\u8bbe\u7f6e\u5b89\u5168\u7ba1\u7406\u5668\n         SecurityUtils.setSecurityManager(defaultSecurityManager);\n         \/\/ 4.\u5173\u952e\u5bf9\u8c61subject\u4e3b\u4f53\n         Subject subject = SecurityUtils.getSubject();\n         \/\/ 5.\u521b\u5efa\u4ee4\u724c\n         UsernamePasswordToken token = new UsernamePasswordToken(\"glj\", \"123456\");\n\n         try {\n             subject.login(token);\n             System.out.println(\"\u767b\u5f55\u6210\u529f\");\n         } catch (AuthenticationException e) {\n             e.printStackTrace();\n         }\n\n\n         if (subject.isAuthenticated()) {\n             System.out.println(\"====== \u6821\u9a8c\u662f\u5426\u5b58\u5728\u6b64\u89d2\u8272\u6743\u9650\u63a7\u5236\");\n             boolean hasRole = subject.hasRole(\"admin\");\n             System.out.println(\"hasRole:\"+hasRole);\n\n\n             System.out.println(\"====== \u6821\u9a8c\u662f\u5426\u5b58\u5728\u591a\u4e2a\u89d2\u8272\u6743\u9650\u63a7\u5236\");\n             boolean hasAllRoles = subject.hasAllRoles(Arrays.asList(\"admin\", \"users\"));\n             System.out.println(\"hasAllRoles:\"+hasAllRoles);\n\n             System.out.println(\"====== \u6821\u9a8c\u662f\u5426\u5b58\u5728\u5176\u4e2d\u4e00\u4e2a\u89d2\u8272\u6743\u9650\u63a7\u5236\");\n             boolean[] hasRoles = subject.hasRoles(Arrays.asList(\"admin\", \"users\", \"update\"));\n             for (boolean b : hasRoles) {\n                 System.out.println(\"b:\"+b);\n             }\n\n             System.out.println(\"====== \u6821\u9a8c\u662f\u5426\u5b58\u5728\u6b64\u8d44\u6e90\u8bbf\u95ee\u6743\u9650\");\n             \/\/ \u57fa\u4e8e\u6743\u9650\u5b57\u7b26\u4e32\u7684\u8bbf\u95ee\u63a7\u5236 \u8d44\u6e90\u6807\u8bc6\u7b26\uff1a\u64cd\u4f5c\uff1a\u8d44\u6e90\u7c7b\u578b\n             boolean subjectPermitted = subject.isPermitted(\"user:*:*\");\n             System.out.println(\"subjectPermitted:\"+subjectPermitted);\n\n             System.out.println(\"====== \u6821\u9a8c\u662f\u5426\u5b58\u5728\u591a\u4e2a\u8d44\u6e90\u8bbf\u95ee\u6743\u9650\");\n             boolean permittedAll = subject.isPermittedAll(\"user:*:*\", \"user:insert:glj\");\n             System.out.println(\"permittedAll:\"+permittedAll);\n\n             System.out.println(\"====== \u6821\u9a8c\u662f\u5426\u5b58\u5728\u5176\u4e2d\u4e00\u4e2a\u8d44\u6e90\u8bbf\u95ee\u6743\u9650\");\n             boolean[] booleans = subject.isPermitted(\"user:*:*\", \"user:insert:glj\");\n             for (boolean aBoolean : booleans) {\n                 System.out.println(\"aBoolean\"+aBoolean);\n             }\n\n         }\n\n     }\n\n}\n<\/code><\/pre>\n<h3>\u516d\u3001\u6574\u5408SpringBoot\u9879\u2f6c\u5b9e\u6218<\/h3>\n<h4>6.1 \u6574\u5408\u601d\u8def<\/h4>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211110221729562.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211110221729562.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211110221729562\" \/><\/div><\/p>\n<h4>6.2 \u5e38\u2ec5\u8fc7\u6ee4\u5668<\/h4>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211111233835160.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211111233835160.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211111233835160\" \/><\/div><\/p>\n<h4>6.3 \u7b80\u5355\u6574\u5408\u4e4b\u8ba4\u8bc1+\u7b80\u5355\u6ce8\u518c\u7684\u5b9e\u73b0<\/h4>\n<h5>6.3.1.\u521b\u5efa\u9879\u2f6c<\/h5>\n<p><code>springboot+shiro<\/code><\/p>\n<h5>6.3.2 \u5f15\u2f0a\u4f9d\u8d56\u53ca\u5176application.properties\u914d\u7f6e<\/h5>\n<pre data-language=XML><code class=\"language-markup line-numbers\">        &lt;dependency&gt;\n            &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n            &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!--\u5f15\u2f0ashiro\u6574\u5408Springboot\u4f9d\u8d56--&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.apache.shiro&lt;\/groupId&gt;\n            &lt;artifactId&gt;shiro-spring-boot-starter&lt;\/artifactId&gt;\n            &lt;version&gt;1.5.3&lt;\/version&gt;\n        &lt;\/dependency&gt;\n        &lt;!--mysql--&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;mysql&lt;\/groupId&gt;\n            &lt;artifactId&gt;mysql-connector-java&lt;\/artifactId&gt;\n            &lt;version&gt;8.0.20&lt;\/version&gt;\n        &lt;\/dependency&gt;\n        &lt;!-- mybatis-plus--&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;com.baomidou&lt;\/groupId&gt;\n            &lt;artifactId&gt;mybatis-plus-boot-starter&lt;\/artifactId&gt;\n            &lt;version&gt;3.4.2&lt;\/version&gt;\n        &lt;\/dependency&gt;\n\n        &lt;!--druia --&gt;\n        &lt;dependency&gt;\n            &lt;groupId&gt;com.alibaba&lt;\/groupId&gt;\n            &lt;artifactId&gt;druid-spring-boot-starter&lt;\/artifactId&gt;\n            &lt;version&gt;1.1.21&lt;\/version&gt;\n        &lt;\/dependency&gt;\n\n        &lt;dependency&gt;\n            &lt;groupId&gt;cn.hutool&lt;\/groupId&gt;\n            &lt;artifactId&gt;hutool-all&lt;\/artifactId&gt;\n            &lt;version&gt;5.7.16&lt;\/version&gt;\n        &lt;\/dependency&gt;\n\n        &lt;dependency&gt;\n            &lt;groupId&gt;org.projectlombok&lt;\/groupId&gt;\n            &lt;artifactId&gt;lombok&lt;\/artifactId&gt;\n            &lt;optional&gt;true&lt;\/optional&gt;\n        &lt;\/dependency&gt;\n<\/code><\/pre>\n<pre><code class=\"language-properties line-numbers\">spring.application.name=shiro\nserver.port=8081\nserver.servlet.context-path=\/shiro\n\nspring.datasource.type=com.alibaba.druid.pool.DruidDataSource\nspring.datasource.url=jdbc:mysql:\/\/127.0.0.1:3306\/shiro?characterEncoding=utf-8&amp;serverTimezone=Asia\/Shanghai\nspring.datasource.username=root\nspring.datasource.password=root\n\n####mybatis-plus\nmybatis-plus.mapper-locations=classpath:mapper\/*.xml\nmybatis-plus.type-aliases-package=com.glj.springboot_shiro.entity\n<\/code><\/pre>\n<h5>6.3.3 \u521b\u5efa\u914d\u7f6e\u7c7b<\/h5>\n<pre><code class=\"language-java line-numbers\">@Configuration\npublic class ShiroConfig {\n\n    \/**\n     * \u521b\u5efashiroFilter\uff0c\u8d1f\u8d23\u62e6\u622a\u6240\u6709\u8bf7\u6c42\n     * @param defaultWebSecurityManager\n     * @return\n     *\/\n    @Bean\n    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){\n\n        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();\n        \/\/ \u7ed9filter \u914d\u7f6e\u5b89\u5168\u7ba1\u7406\u5668\n        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);\n        \/\/ \u914d\u7f6e\u7cfb\u7edf\u53d7\u9650\u8d44\u6e90\n        \/\/ \u914d\u7f6e\u7cfb\u7edf\u516c\u5171\u8d44\u6e90\n        Map&lt;String, String&gt; map = new HashMap&lt;&gt;();\n        map.put(\"\/**\",\"authc\");\n        \/\/ \u8bbe\u7f6e\u767b\u51fa\n        map.put(\"\/logout\", \"logout\");\n        map.put(\"\/login\",\"anon\");\n        map.put(\"\/register\", \"anon\");\n        \/\/ \u8bbe\u7f6e\u9ed8\u8ba4\u7684\u767b\u5f55\u63a5\u53e3...\n        shiroFilterFactoryBean.setLoginUrl(\"\/loginIndex\");\n        \/\/ \u8bbe\u7f6e\u9519\u8bef\u9875\u9762,\u8ba4\u8bc1\u4e0d\u901a\u8fc7\u8df3\u8f6c\n        shiroFilterFactoryBean.setUnauthorizedUrl(\"\/error\");\n\n        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);\n        return shiroFilterFactoryBean;\n    }\n\n    \/**\n     * \u521b\u5efa\u5b89\u5168\u7ba1\u7406\u5668\n     * @return\n     *\/\n    @Bean\n    public DefaultWebSecurityManager getDefaultWebSecurityManager(){\n        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();\n        defaultWebSecurityManager.setRealm(realm());\n        return defaultWebSecurityManager;\n    }\n\n    \/**\n     * \u521b\u5efa\u81ea\u5b9a\u4e49\u7684realm\n     * @return\n     *\/\n    @Bean\n    public Realm realm(){\n        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();\n        \/\/ MD5\u3001Salt\u7684\u8ba4\u8bc1\u5b9e\u73b0\n        hashedCredentialsMatcher.setHashAlgorithmName(\"md5\");\n        hashedCredentialsMatcher.setHashIterations(1024);\n        CustomRealm customRealm = new CustomRealm();\n        customRealm.setCredentialsMatcher(hashedCredentialsMatcher);\n        return customRealm;\n    }\n}\n\n\n\n@MapperScan(\"com.glj.springboot_shiro.mapper\")\n@Configuration\npublic class MybatisConfig {\n    \/**\n     * \u9632\u6b62\u51fa\u73b0\u6ca1\u627e\u5230mapper\u7684\u8b66\u544a\n     *\/\n    @Mapper\n    public interface NoWarnMapper {\n    }\n}\n<\/code><\/pre>\n<h5>6.3.4 \u521b\u5efa\u81ea\u5b9a\u4e49\u7684realm(\u6682\u65f6\u662f\u53ea\u6709 MD5+Salt+hash\u7684\u8ba4\u8bc1\u5b9e\u73b0)<\/h5>\n<pre><code class=\"language-java line-numbers\">@Component\npublic class CustomRealm extends AuthorizingRealm {\n\n    @Autowired\n    private UserService userService;\n\n    @Override\n    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {\n        return null;\n    }\n\n    \/**\n     * \u8ba4\u8bc1\n     * @param authenticationToken\n     * @return\n     * @throws AuthenticationException\n     *\/\n    @Override\n    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {\n        System.out.println(\"======doGetAuthenticationInfo=====\");\n        if (StringUtils.isEmpty(authenticationToken.getPrincipal())) {\n            return null;\n        }\n        UsernamePasswordToken usernamePasswordToken  = (UsernamePasswordToken) authenticationToken;\n        String username = usernamePasswordToken.getUsername();\n        User user = userService.findByUserName(username);\n        if (user !=null) {\n            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName());\n            return simpleAuthenticationInfo;\n        }\n        return null;\n    }\n}\n<\/code><\/pre>\n<h5>6.3.5 \u521b\u5efaentity+user\u8868<\/h5>\n<pre><code class=\"language-java line-numbers\">@Data\n@Accessors(chain = true)\n@AllArgsConstructor\n@NoArgsConstructor\n@TableName(\"t_user\")\npublic class User {\n\n    private String id;\n    private String username;\n    private String password;\n    private String salt;\n\n}\n<\/code><\/pre>\n<pre><code class=\"language-sql line-numbers\">CREATE TABLE `t_user` (\n  `id` varchar(40) NOT NULL,\n  `username` varchar(40) DEFAULT NULL,\n  `password` varchar(40) DEFAULT NULL,\n  `salt` varchar(100) DEFAULT NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n<\/code><\/pre>\n<h5>6.3.6 \u521b\u5efaMapper\u63a5\u2f1d<\/h5>\n<pre><code class=\"language-java line-numbers\">@Repository\npublic interface UserMapper extends BaseMapper&lt;User&gt; {\n\n}\n<\/code><\/pre>\n<h5>6.3.7 \u5f00\u53d1service\u63a5\u2f1d<\/h5>\n<pre><code class=\"language-java line-numbers\">public interface UserService {\n\n    \/**\n     * \u6ce8\u518c\n     * @param user\n     *\/\n    void register(User user);\n\n    \/**\n     * \u6839\u636euserName\u67e5\u627e\u7528\u6237\u4fe1\u606f\n     * @param userName\n     * @return\n     *\/\n    User findByUserName(String userName);\n\n}\n\n@Slf4j\n@Service\npublic class UserServiceImpl implements UserService{\n\n    @Autowired\n    private UserMapper userMapper;\n\n    @Override\n    public void register(User user) {\n        log.info(\"user.getPassword():\"+user.getPassword());\n        \/\/ \u5904\u7406\u4e1a\u52a1 md5+salt+hash\n        String userId = IdUtil.simpleUUID();\n        user.setId(userId);\n        String salt = new Md5Hash(userId).toHex();\n        user.setSalt(salt);\n        Md5Hash md5Hash = new Md5Hash(user.getPassword(), salt, 1024);\n        user.setPassword(md5Hash.toHex());\n        userMapper.insert(user);\n    }\n\n    @Override\n    public User findByUserName(String userName) {\n        QueryWrapper queryWrapper =new QueryWrapper();\n        queryWrapper.eq(\"username\",userName);\n        User user = userMapper.selectOne(queryWrapper);\n        return user;\n    }\n}\n<\/code><\/pre>\n<h5>6.3.8 \u521b\u5efaController<\/h5>\n<pre><code class=\"language-java line-numbers\">@Slf4j\n@RestController\npublic class IndexController {\n\n    @GetMapping(\"\/index\")\n    public String index(){\n        return \"this is index...\";\n    }\n\n    @GetMapping(\"\/error\")\n    public String error(){\n        return \"this is error...\";\n    }\n\n}\n\n@Slf4j\n@RestController\npublic class LoginController {\n\n    @GetMapping(\"\/logout\")\n    public String logout(){\n        Subject subject = SecurityUtils.getSubject();\n        subject.logout();\n        return \"logout page\";\n    }\n\n    @GetMapping(\"\/loginIndex\")\n    public String loginIndex(){\n        return \"loginIndex...\";\n    }\n\n    @GetMapping(\"\/login\")\n    public String login(String username,String password){\n        Subject subject = SecurityUtils.getSubject();\n        try {\n            subject.login(new UsernamePasswordToken(username,password));\n            return \"login success\";\n        } catch (UnknownAccountException e) {\n            System.out.println(\"\u2f64\u2f3e\u540d\u9519\u8bef\");\n        } catch (IncorrectCredentialsException e){\n            System.out.println(\"\u5bc6\u7801\u9519\u8bef\");\n        }\n        return \"login ...........fail\";\n    }\n\n}\n\n@Slf4j\n@RestController\npublic class RegisterController {\n\n    @Autowired\n    private UserService userService;\n\n    @PostMapping(\"\/register\")\n    public String register(User user){\n        try {\n            userService.register(user);\n            return \"register success\";\n        } catch (Exception e) {\n            return \"register ...........fail\";\n        }\n    }\n\n}\n<\/code><\/pre>\n<h5>6.3.9 \u8fdb\u884c\u63a5\u53e3\u6d4b\u8bd5<\/h5>\n<pre><code class=\"language-url line-numbers\"># \u6ce8\u518c\u540e\u89c2\u5bdf\u6570\u636e\u5e93\n127.0.0.1:8081\/shiro\/register?username=glj&amp;password=glj\n# \u6d4b\u8bd5\u662f\u5426\u80fd\u6b63\u5e38\u767b\u5f55\n127.0.0.1:8081\/shiro\/login?username=glj&amp;password=glj\n<\/code><\/pre>\n<h4>6.4 \u7b80\u5355\u6574\u5408\u4e4b\u6388\u6743\u7684\u5b9e\u73b0<\/h4>\n<h5>6.4.1 \u6388\u6743\u7684\u6d41\u7a0b\u8868<\/h5>\n<p><div class='fancybox-wrapper lazyload-container-unload' data-fancybox='post-images' href='https:\/\/qn.199604.com\/typoraImg\/image-20211113224749639.png'><img class=\"lazyload lazyload-style-1\" src=\"data:image\/svg+xml;base64,PCEtLUFyZ29uTG9hZGluZy0tPgo8c3ZnIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgc3Ryb2tlPSIjZmZmZmZmMDAiPjxnPjwvZz4KPC9zdmc+\"  decoding=\"async\" data-original=\"https:\/\/qn.199604.com\/typoraImg\/image-20211113224749639.png\" src=\"data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB\/AAffA0nNPuCLAAAAAElFTkSuQmCC\" alt=\"image-20211113224749639\" \/><\/div><\/p>\n<h5>6.4.2 \u6570\u636e\u5e93\u7684\u5efa\u8868\u8bed\u53e5+entity\u8868<\/h5>\n<pre><code class=\"language-sql line-numbers\">-- ----------------------------\n-- Table structure for t_perms\n-- ----------------------------\nDROP TABLE IF EXISTS `t_perms`;\nCREATE TABLE `t_perms`  (\n  `id` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\n  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;\n\n-- ----------------------------\n-- Table structure for t_role\n-- ----------------------------\nDROP TABLE IF EXISTS `t_role`;\nCREATE TABLE `t_role`  (\n  `id` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\n  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;\n\n-- ----------------------------\n-- Table structure for t_role_perms\n-- ----------------------------\nDROP TABLE IF EXISTS `t_role_perms`;\nCREATE TABLE `t_role_perms`  (\n  `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\n  `roleid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `permsid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;\n\n-- ----------------------------\n-- Table structure for t_user\n-- ----------------------------\nDROP TABLE IF EXISTS `t_user`;\nCREATE TABLE `t_user`  (\n  `id` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\n  `username` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `password` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `salt` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;\n\n-- ----------------------------\n-- Table structure for t_user_role\n-- ----------------------------\nDROP TABLE IF EXISTS `t_user_role`;\nCREATE TABLE `t_user_role`  (\n  `id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,\n  `userid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  `roleid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,\n  PRIMARY KEY (`id`) USING BTREE\n) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;\n\nSET FOREIGN_KEY_CHECKS = 1;\n\n<\/code><\/pre>\n<pre><code class=\"language-java line-numbers\">@Data\n@Accessors(chain = true)\n@AllArgsConstructor\n@NoArgsConstructor\n@TableName(\"t_user\")\npublic class User {\n\n    private String id;\n    private String username;\n    private String password;\n    private String salt;\n\n    \/\/ \u5b9a\u4e49\u2ec6\u2f8a\u96c6\u5408\n    @TableField(exist=false)\n    private List&lt;Role&gt; roles;\n\n}\n\n@Data\n@Accessors(chain = true)\n@AllArgsConstructor\n@NoArgsConstructor\n@TableName(\"t_role\")\npublic class Role {\n\n    private String id;\n    private String name;\n\n    \/\/ \u5b9a\u4e49\u6743\u9650\u7684\u96c6\u5408\n    @TableField(exist=false)\n    private List&lt;Perms&gt; perms;\n\n}\n\n@Data\n@NoArgsConstructor\n@AllArgsConstructor\n@Accessors(chain = true)\n@TableName(\"t_perms\")\npublic class Perms {\n\n    private String id;\n    private String name;\n    private String url;\n\n}\n<\/code><\/pre>\n<h5>6.4.3 \u521b\u5efaMapper\u2f45\u6cd5<\/h5>\n<pre><code class=\"language-java line-numbers\">@Repository\npublic interface UserMapper extends BaseMapper&lt;User&gt; {\n\n    \/**\n     * \u6839\u636e\u2f64\u2f3e\u540d\u67e5\u8be2\u6240\u6709\u2ec6\u2f8a\n     * @param username\n     * @return\n     *\/\n    User findRolesByUserName(String username);\n    \/**\n     * \u6839\u636e\u2ec6\u2f8aid\u67e5\u8be2\u6743\u9650\u96c6\u5408\n     * @param roleId\n     * @return\n     *\/\n    List&lt;Perms&gt; findPermsByRoleId(String roleId);\n}\n\n<\/code><\/pre>\n<h6>UserMapper.xml<\/h6>\n<pre data-language=XML><code class=\"language-markup line-numbers\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;!DOCTYPE mapper PUBLIC \"-\/\/mybatis.org\/\/DTD Mapper 3.0\/\/EN\"\n        \"http:\/\/mybatis.org\/dtd\/mybatis-3-mapper.dtd\"&gt;\n&lt;mapper namespace=\"com.glj.springboot_shiro.mapper.UserMapper\"&gt;\n\n    &lt;resultMap id=\"userMap\" type=\"com.glj.springboot_shiro.entity.User\"&gt;\n        &lt;id column=\"uid\" property=\"id\"\/&gt;\n        &lt;result column=\"username\" property=\"username\"\/&gt;\n        &lt;!--\u2ec6\u2f8a\u4fe1\u606f--&gt;\n        &lt;collection property=\"roles\" javaType=\"list\" ofType=\"com.glj.springboot_shiro.entity.Role\"&gt;\n            &lt;id column=\"rid\" property=\"id\"\/&gt;\n            &lt;result column=\"rname\" property=\"name\"\/&gt;\n        &lt;\/collection&gt;\n    &lt;\/resultMap&gt;\n\n    &lt;select id=\"findRolesByUserName\" parameterType=\"String\" resultMap=\"userMap\"&gt;\n        SELECT u.id as uid,u.username,r.id as rid,r.name as rname FROM t_user u\n        LEFT JOIN t_user_role ur ON u.id=ur.userid\n        LEFT JOIN t_role r ON ur.roleid=r.id\n        WHERE u.username=#{username}\n    &lt;\/select&gt;\n\n    &lt;select id=\"findPermsByRoleId\" parameterType=\"String\" resultType=\"com.glj.springboot_shiro.entity.Perms\"&gt;\n        SELECT p.id,p.name,p.url\n        FROM t_role r\n        LEFT JOIN t_role_perms rp\n        ON r.id=rp.roleid\n        LEFT JOIN t_perms p ON rp.permsid=p.id\n        WHERE r.id=#{id}\n    &lt;\/select&gt;\n\n&lt;\/mapper&gt;\n\n<\/code><\/pre>\n<h5>6.4.4 \u5f00\u53d1serivce:<\/h5>\n<pre><code class=\"language-java line-numbers\">public interface UserService {\n\n    \/**\n     * \u6ce8\u518c\n     * @param user\n     *\/\n    void register(User user);\n\n    \/**\n     * \u6839\u636euserName\u67e5\u627e\u7528\u6237\u4fe1\u606f\n     * @param userName\n     * @return\n     *\/\n    User findByUserName(String userName);\n\n    \/**\n     * \u6839\u636e\u2f64\u2f3e\u540d\u67e5\u8be2\u6240\u6709\u2ec6\u2f8a\n     * @param username\n     * @return\n     *\/\n    User findRolesByUserName(String username);\n\n\n    \/**\n     * \u6839\u636e\u2ec6\u2f8aid\u67e5\u8be2\u6743\u9650\u96c6\u5408\n     * @param roleId\n     * @return\n     *\/\n    List&lt;Perms&gt; findPermsByRoleId(String roleId);\n}\n\n\n@Slf4j\n@Service\npublic class UserServiceImpl implements UserService{\n\n    @Autowired\n    private UserMapper userMapper;\n\n    @Override\n    public void register(User user) {\n        log.info(\"user.getPassword():\"+user.getPassword());\n        \/\/ \u5904\u7406\u4e1a\u52a1 md5+salt+hash\n        String userId = IdUtil.simpleUUID();\n        user.setId(userId);\n        String salt = new Md5Hash(userId).toHex();\n        user.setSalt(salt);\n        Md5Hash md5Hash = new Md5Hash(user.getPassword(), salt, 1024);\n        user.setPassword(md5Hash.toHex());\n        userMapper.insert(user);\n    }\n\n    @Override\n    public User findByUserName(String userName) {\n        QueryWrapper queryWrapper =new QueryWrapper();\n        queryWrapper.eq(\"username\",userName);\n        User user = userMapper.selectOne(queryWrapper);\n        return user;\n    }\n\n    @Override\n    public User findRolesByUserName(String username) {\n        return userMapper.findRolesByUserName(username);\n    }\n\n    @Override\n    public List&lt;Perms&gt; findPermsByRoleId(String roleId) {\n        return userMapper.findPermsByRoleId(roleId);\n    }\n\n\n}\n<\/code><\/pre>\n<h5>6.4.5 \u521b\u5efaController<\/h5>\n<pre><code class=\"language-java line-numbers\">@Slf4j\n@RestController\npublic class IndexController {\n\n    @RequiresPermissions(\"admin:*:*\")\n    @GetMapping(\"\/perms\")\n    public String perms(){\n        return \"this is perms...\";\n    }\n\n    @RequiresRoles(\"admin\")\n    @GetMapping(\"\/admin\")\n    public String admin(){\n        return \"this is admin...\";\n    }\n\n    @GetMapping(\"\/index\")\n    public String index(){\n        return \"this is index...\";\n    }\n\n    @GetMapping(\"\/error\")\n    public String error(){\n        return \"this is error...\";\n    }\n\n}\n\n\n@Slf4j\n@RestController\npublic class LoginController {\n\n    @GetMapping(\"\/logout\")\n    public String logout(){\n        Subject subject = SecurityUtils.getSubject();\n        subject.logout();\n        return \"logout page\";\n    }\n\n    @GetMapping(\"\/loginIndex\")\n    public String loginIndex(){\n        return \"loginIndex...\";\n    }\n\n    @GetMapping(\"\/login\")\n    public String login(String username,String password){\n        Subject subject = SecurityUtils.getSubject();\n        try {\n            subject.login(new UsernamePasswordToken(username,password));\n            return \"login success\";\n        } catch (UnknownAccountException e) {\n            System.out.println(\"\u2f64\u2f3e\u540d\u9519\u8bef\");\n        } catch (IncorrectCredentialsException e){\n            System.out.println(\"\u5bc6\u7801\u9519\u8bef\");\n        }\n        return \"login ...........fail\";\n    }\n\n}\n<\/code><\/pre>\n<h5>6.4.6 \u8fdb\u884c\u63a5\u53e3\u6d4b\u8bd5<\/h5>\n<pre><code class=\"language-txt line-numbers\"># \u767b\u5f55\n127.0.0.1:8081\/shiro\/login?username=glj&amp;password=glj\n# \u6d4b\u8bd5admin\u6743\u9650\n127.0.0.1:8081\/shiro\/admin\n# \u6d4b\u8bd5perms\u6388\u6743\u9875\u9762\n127.0.0.1:8081\/shiro\/perms\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Shiro\u6846\u67b6\u5feb\u901f\u5b66\u4e60\u672d\u8bb0 \u2f00\u3001\u6743\u9650\u7684\u7ba1\u7406 1.1 \u4ec0\u4e48\u662f\u6743\u9650\u7ba1\u7406 \u57fa\u672c\u4e0a\u6d89\u53ca\u5230\u2f64\u2f3e\u53c2\u4e0e\u7684\u7cfb\u7edf\u90fd\u8981\u8fdb\u2f8f\u6743\u9650\u7ba1\u7406 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[292,130,327],"tags":[129,166],"class_list":{"0":"post-1997","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"hentry","6":"category-java","8":"category-shiro","9":"tag-java","10":"tag-shiro"},"_links":{"self":[{"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/posts\/1997","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/comments?post=1997"}],"version-history":[{"count":2,"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/posts\/1997\/revisions"}],"predecessor-version":[{"id":2010,"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/posts\/1997\/revisions\/2010"}],"wp:attachment":[{"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/media?parent=1997"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/categories?post=1997"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/199604.com\/wp-json\/wp\/v2\/tags?post=1997"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}