privilege_权限控制设计思路.html 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>privilege_权限控制设计思路</title>
  5. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  6. <style type="text/css">
  7. /* GitHub stylesheet for MarkdownPad (http://markdownpad.com) */
  8. /* Author: Nicolas Hery - http://nicolashery.com */
  9. /* Version: b13fe65ca28d2e568c6ed5d7f06581183df8f2ff */
  10. /* Source: https://github.com/nicolahery/markdownpad-github */
  11. /* RESET
  12. =============================================================================*/
  13. html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
  14. margin: 0;
  15. padding: 0;
  16. border: 0;
  17. }
  18. /* BODY
  19. =============================================================================*/
  20. body {
  21. font-family: Helvetica, arial, freesans, clean, sans-serif;
  22. font-size: 14px;
  23. line-height: 1.6;
  24. color: #333;
  25. background-color: #fff;
  26. padding: 20px;
  27. max-width: 960px;
  28. margin: 0 auto;
  29. }
  30. body>*:first-child {
  31. margin-top: 0 !important;
  32. }
  33. body>*:last-child {
  34. margin-bottom: 0 !important;
  35. }
  36. /* BLOCKS
  37. =============================================================================*/
  38. p, blockquote, ul, ol, dl, table, pre {
  39. margin: 15px 0;
  40. }
  41. /* HEADERS
  42. =============================================================================*/
  43. h1, h2, h3, h4, h5, h6 {
  44. margin: 20px 0 10px;
  45. padding: 0;
  46. font-weight: bold;
  47. -webkit-font-smoothing: antialiased;
  48. }
  49. h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
  50. font-size: inherit;
  51. }
  52. h1 {
  53. font-size: 28px;
  54. color: #000;
  55. }
  56. h2 {
  57. font-size: 24px;
  58. border-bottom: 1px solid #ccc;
  59. color: #000;
  60. }
  61. h3 {
  62. font-size: 18px;
  63. }
  64. h4 {
  65. font-size: 16px;
  66. }
  67. h5 {
  68. font-size: 14px;
  69. }
  70. h6 {
  71. color: #777;
  72. font-size: 14px;
  73. }
  74. body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
  75. margin-top: 0;
  76. padding-top: 0;
  77. }
  78. a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  79. margin-top: 0;
  80. padding-top: 0;
  81. }
  82. h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
  83. margin-top: 10px;
  84. }
  85. /* LINKS
  86. =============================================================================*/
  87. a {
  88. color: #4183C4;
  89. text-decoration: none;
  90. }
  91. a:hover {
  92. text-decoration: underline;
  93. }
  94. /* LISTS
  95. =============================================================================*/
  96. ul, ol {
  97. padding-left: 30px;
  98. }
  99. ul li > :first-child,
  100. ol li > :first-child,
  101. ul li ul:first-of-type,
  102. ol li ol:first-of-type,
  103. ul li ol:first-of-type,
  104. ol li ul:first-of-type {
  105. margin-top: 0px;
  106. }
  107. ul ul, ul ol, ol ol, ol ul {
  108. margin-bottom: 0;
  109. }
  110. dl {
  111. padding: 0;
  112. }
  113. dl dt {
  114. font-size: 14px;
  115. font-weight: bold;
  116. font-style: italic;
  117. padding: 0;
  118. margin: 15px 0 5px;
  119. }
  120. dl dt:first-child {
  121. padding: 0;
  122. }
  123. dl dt>:first-child {
  124. margin-top: 0px;
  125. }
  126. dl dt>:last-child {
  127. margin-bottom: 0px;
  128. }
  129. dl dd {
  130. margin: 0 0 15px;
  131. padding: 0 15px;
  132. }
  133. dl dd>:first-child {
  134. margin-top: 0px;
  135. }
  136. dl dd>:last-child {
  137. margin-bottom: 0px;
  138. }
  139. /* CODE
  140. =============================================================================*/
  141. pre, code, tt {
  142. font-size: 12px;
  143. font-family: Consolas, "Liberation Mono", Courier, monospace;
  144. }
  145. code, tt {
  146. margin: 0 0px;
  147. padding: 0px 0px;
  148. white-space: nowrap;
  149. border: 1px solid #eaeaea;
  150. background-color: #f8f8f8;
  151. border-radius: 3px;
  152. }
  153. pre>code {
  154. margin: 0;
  155. padding: 0;
  156. white-space: pre;
  157. border: none;
  158. background: transparent;
  159. }
  160. pre {
  161. background-color: #f8f8f8;
  162. border: 1px solid #ccc;
  163. font-size: 13px;
  164. line-height: 19px;
  165. overflow: auto;
  166. padding: 6px 10px;
  167. border-radius: 3px;
  168. }
  169. pre code, pre tt {
  170. background-color: transparent;
  171. border: none;
  172. }
  173. kbd {
  174. -moz-border-bottom-colors: none;
  175. -moz-border-left-colors: none;
  176. -moz-border-right-colors: none;
  177. -moz-border-top-colors: none;
  178. background-color: #DDDDDD;
  179. background-image: linear-gradient(#F1F1F1, #DDDDDD);
  180. background-repeat: repeat-x;
  181. border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
  182. border-image: none;
  183. border-radius: 2px 2px 2px 2px;
  184. border-style: solid;
  185. border-width: 1px;
  186. font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
  187. line-height: 10px;
  188. padding: 1px 4px;
  189. }
  190. /* QUOTES
  191. =============================================================================*/
  192. blockquote {
  193. border-left: 4px solid #DDD;
  194. padding: 0 15px;
  195. color: #777;
  196. }
  197. blockquote>:first-child {
  198. margin-top: 0px;
  199. }
  200. blockquote>:last-child {
  201. margin-bottom: 0px;
  202. }
  203. /* HORIZONTAL RULES
  204. =============================================================================*/
  205. hr {
  206. clear: both;
  207. margin: 15px 0;
  208. height: 0px;
  209. overflow: hidden;
  210. border: none;
  211. background: transparent;
  212. border-bottom: 4px solid #ddd;
  213. padding: 0;
  214. }
  215. /* TABLES
  216. =============================================================================*/
  217. table th {
  218. font-weight: bold;
  219. }
  220. table th, table td {
  221. border: 1px solid #ccc;
  222. padding: 6px 13px;
  223. }
  224. table tr {
  225. border-top: 1px solid #ccc;
  226. background-color: #fff;
  227. }
  228. table tr:nth-child(2n) {
  229. background-color: #f8f8f8;
  230. }
  231. /* IMAGES
  232. =============================================================================*/
  233. img {
  234. max-width: 100%
  235. }
  236. </style>
  237. </head>
  238. <body>
  239. <h1>privilege_权限控制设计思路</h1>
  240. <blockquote>
  241. <p>本文档主要是简单描述下权限控制的主要部分。</p>
  242. </blockquote>
  243. <h2>基本脉络</h2>
  244. <blockquote>
  245. <p>主要分成5个部分。</p>
  246. </blockquote>
  247. <ol>
  248. <li>三个权限基础数据对象和URI</li>
  249. <li>组织基础数据对象</li>
  250. <li>角色、用户的权限表</li>
  251. <li>角色、用户的权限数据(用于访问控制、给其它用户配置权限)</li>
  252. <li>基于用户的权限数据生成有层级的访问菜单</li>
  253. </ol>
  254. <h2>分解</h2>
  255. <h3>1. 三个权限基础数据对象和URI</h3>
  256. <p>包含 <strong>URI.java,PNode.java, PModule.java, PMenu.java</strong> 对象</p>
  257. <blockquote>
  258. <p>URI: 字面意思,所有Controller的@RequestMapping的value都在此对象定义。<br>
  259. PNode: 定义最细粒度的权限控制节点,也能起到聚合控制的作用。<br>
  260. PModule: 定义模块和模块下拥有的多个PNode节点。<br>
  261. PMenu: 定义访问菜单。聚合PModule定义的模块到菜单下。初步形成有层级的访问菜单。</p>
  262. </blockquote>
  263. <p>彼此关联:</p>
  264. <p><img src="menu_module_node_uri_ctrl.jpg" alt="menu_module_node_uri_ctrl.jpg" /></p>
  265. <h3>2. 组织基础数据对象</h3>
  266. <p>依据PMenu的配置代码,生成树形菜单的数据结构。</p>
  267. <h4>Menu.java</h4>
  268. <pre><code>public class Menu {
  269. private int id; // 当前ID PMenu.ordinal() + 1;
  270. private int pid = 0; // 父id PMenu.ordinal() + 1
  271. private String name; // 菜单名称
  272. private List&lt;Module&gt; moduleList = new ArrayList&lt;&gt;(); // 模块列表
  273. private List&lt;Menu&gt; subList = new ArrayList&lt;&gt;(); // 子菜单列表
  274. }
  275. </code></pre>
  276. <h4>Module.java</h4>
  277. <pre><code>public class Module {
  278. private final int id; // PModule.ordinal() + 100;
  279. private final int pid; // Menu实例的id
  280. private final String pname; // 模块的值、名称
  281. private final String desc;
  282. private final List&lt;PNode&gt; nodeList = new ArrayList&lt;&gt;(); // 节点列表
  283. }
  284. </code></pre>
  285. <p>结合以上两数据对象,生成层级菜单(<code>List&lt;Menu&gt;</code>),供权限配置。<br>
  286. 前端的层级展示采用 <a href="http://maxazan.github.io/jquery-treegrid/">jquery-treegrid</a> .</p>
  287. <h4><code>List&lt;Menu&gt;</code> 数据结构示例</h4>
  288. <pre><code>[{
  289. &quot;id&quot;: 1,
  290. &quot;pid&quot;: 0,
  291. &quot;name&quot;: &quot;系统基本配置&quot;,
  292. &quot;moduleList&quot;: [{
  293. &quot;id&quot;: 101,
  294. &quot;pid&quot;: 1,
  295. &quot;pname&quot;: &quot;privilege_role&quot;,
  296. &quot;desc&quot;: &quot;角色管理配置&quot;,
  297. &quot;nodeList&quot;: [&quot;MANAGER&quot;,
  298. &quot;NEW&quot;,
  299. &quot;GET&quot;,
  300. &quot;EDIT&quot;]
  301. },
  302. {
  303. &quot;id&quot;: 102,
  304. &quot;pid&quot;: 1,
  305. &quot;pname&quot;: &quot;privilege_user&quot;,
  306. &quot;desc&quot;: &quot;用户管理配置&quot;,
  307. &quot;nodeList&quot;: [&quot;MANAGER&quot;,
  308. &quot;NEW&quot;,
  309. &quot;GET&quot;,
  310. &quot;EDIT&quot;]
  311. }],
  312. &quot;subList&quot;: []
  313. }]
  314. </code></pre>
  315. <h3>3. 角色、用户的权限和表</h3>
  316. <blockquote>
  317. <ol>
  318. <li>模块的权限表示,这里采用 <strong>索引字符</strong> 表示法。&quot;10000000&quot;的权限字符串,表示只有模块的PNode.MANAGER节点的访问、操作权限。(<strong>PNode.index</strong> 即是索引)</li>
  319. <li>权限表只有模块和模块的权限数据,没有菜单结构的数据。<br>
  320. <em>所以需要通过权限的模块,倒序生成出用户的访问菜单,后面会涉及。</em></li>
  321. </ol>
  322. </blockquote>
  323. <p>先看表数据:</p>
  324. <h5>角色权限表数据</h5>
  325. <p><img src="privilege_role.jpg" alt="privilege_role.jpg" /> <br></p>
  326. <p>表结构比较简单,只有模块名、角色拥有的权限。</p>
  327. <h5>用户权限表数据</h5>
  328. <p><img src="privilege_user.jpg" alt="privilege_user.jpg" /><br></p>
  329. <p>表结构同样只有模块名、角色拥有的权限。不过此表数据分两种情况:<br></p>
  330. <blockquote>
  331. <ol>
  332. <li>role_id &gt; 0:表示基于角色给用户配置了权限。用户的权限数据直接定位到角色的权限数据。<br></li>
  333. <li>role_id==0: 表示此表里 <strong><code>user_id</code></strong> 指定的,即是用户的权限数据。</li>
  334. </ol>
  335. </blockquote>
  336. <h3>4. 角色、用户的权限数据(用于访问控制、给其它用户配置权限)</h3>
  337. <ol>
  338. <li>用户可访问的模块和模块的节点,由权限数据表示。</li>
  339. <li>用户给其它用户配置的权限数据在自己的权限数据范围内。</li>
  340. </ol>
  341. <h5>用于访问控制的权限数据</h5>
  342. <blockquote>
  343. <ol>
  344. <li>
  345. 生成: <br>
  346. 读取用户权限表数据--&gt;对照PModule的定义将权限的字符表示转化为节点值列表。
  347. </li>
  348. <li>控制: 见 <code>MySecurityPrivilegeFilter</code> 的实现。有在 <code>web.xml</code> 配置此Filter。</li>
  349. <li>结构:<br></li>
  350. </ol>
  351. </blockquote>
  352. <pre><code>List&lt;Map&lt;String, List&lt;String&gt;&gt;&gt; // List&lt;Map&lt;PModule.pname, List&lt;PNode.pname&gt;&gt;&gt;
  353. 数据示例(json):
  354. [{
  355. &quot;privilege_role&quot;: [&quot;manager&quot;,
  356. &quot;new&quot;,
  357. &quot;get&quot;,
  358. &quot;edit&quot;]
  359. },
  360. {
  361. &quot;privilege_user&quot;: [&quot;manager&quot;,
  362. &quot;new&quot;]
  363. }]
  364. </code></pre>
  365. <h5>给其它用户配置权限的权限数据</h5>
  366. <h6>1. 生成:</h6>
  367. <p>基于用户的【访问控制的权限数据】(<code>List&lt;Map&lt;String, List&lt;String&gt;&gt;&gt;</code>)进一步生成有结构的菜单(<strong><code>List&lt;Menu&gt;</code></strong>)。</p>
  368. <h6>2. 实现:</h6>
  369. <p>见 <code>PrivilegeService</code>。用户登录成功时加载,仅加载一次,并加到Session属性。加载见: <code>MyAuthenticationSuccessHandler</code> 对象。</p>
  370. <h6>3. 数据结构范例:</h6>
  371. <pre><code>[{
  372. &quot;id&quot;: 1,
  373. &quot;pid&quot;: 0,
  374. &quot;name&quot;: &quot;系统基本配置&quot;,
  375. &quot;moduleList&quot;: [{
  376. &quot;id&quot;: 101,
  377. &quot;pid&quot;: 1,
  378. &quot;pname&quot;: &quot;privilege_role&quot;,
  379. &quot;desc&quot;: &quot;角色管理配置&quot;,
  380. &quot;nodeList&quot;: [&quot;MANAGER&quot;,
  381. &quot;NEW&quot;,
  382. &quot;GET&quot;,
  383. &quot;EDIT&quot;]
  384. },
  385. {
  386. &quot;id&quot;: 102,
  387. &quot;pid&quot;: 1,
  388. &quot;pname&quot;: &quot;privilege_user&quot;,
  389. &quot;desc&quot;: &quot;用户管理配置&quot;,
  390. &quot;nodeList&quot;: [&quot;MANAGER&quot;,
  391. &quot;NEW&quot;,
  392. &quot;GET&quot;,
  393. &quot;EDIT&quot;]
  394. }],
  395. &quot;subList&quot;: []
  396. }]
  397. </code></pre>
  398. <h3>5. 基于用户的权限数据生成层级访问菜单</h3>
  399. <h6>1. 生成:</h6>
  400. <p>基于用户的【访问控制的权限数据】(<code>List&lt;Map&lt;String, List&lt;String&gt;&gt;&gt;</code>),
  401. 结合PMenu的菜单与子菜单定义,由模块值逆序找到模块、找到拥有此模块的菜单、继续找父菜单。生成用于访问的树形菜单(<strong><code>List&lt;AccessMenu&gt;</code></strong>)。</p>
  402. <h6>2. 层级菜单的数据对象:</h6>
  403. <p>AccessMenu:</p>
  404. <pre><code>public class AccessMenu {
  405. private final String desc;
  406. private final List&lt;AccessModule&gt; moduleList = new ArrayList&lt;&gt;();
  407. private final List&lt;AccessMenu&gt; subMenuList = new ArrayList&lt;&gt;();
  408. }
  409. </code></pre>
  410. <p>AccessModule:</p>
  411. <pre><code>public class AccessModule {
  412. private final String desc;
  413. private final String uri;
  414. }
  415. </code></pre>
  416. <h6>3. 代码实现:</h6>
  417. <pre><code>见 PrivilegeService.mineAccessMenu()
  418. </code></pre>
  419. <h6>4. 数据结构范例:</h6>
  420. <pre><code>[{
  421. &quot;desc&quot;: &quot;系统基本配置&quot;,
  422. &quot;moduleList&quot;: [{
  423. &quot;desc&quot;: &quot;权限基础数据&quot;,
  424. &quot;uri&quot;: &quot;/hs/privilege/manager&quot;
  425. },
  426. {
  427. &quot;desc&quot;: &quot;角色管理配置&quot;,
  428. &quot;uri&quot;: &quot;/hs/privilege_role/manager&quot;
  429. },
  430. {
  431. &quot;desc&quot;: &quot;用户管理配置&quot;,
  432. &quot;uri&quot;: &quot;/hs/privilege_user/manager&quot;
  433. }],
  434. &quot;subMenuList&quot;: [{
  435. &quot;desc&quot;: &quot;测试2&quot;,
  436. &quot;moduleList&quot;: [{
  437. &quot;desc&quot;: &quot;用户管理&quot;,
  438. &quot;uri&quot;: &quot;/hs/user/manager&quot;
  439. }],
  440. &quot;subMenuList&quot;: []
  441. }]
  442. },
  443. {
  444. &quot;desc&quot;: &quot;测试&quot;,
  445. &quot;moduleList&quot;: [{
  446. &quot;desc&quot;: &quot;用户管理配置&quot;,
  447. &quot;uri&quot;: &quot;/hs/privilege_user/manager&quot;
  448. }],
  449. &quot;subMenuList&quot;: []
  450. }]
  451. </code></pre>
  452. <p>其中 subMenuList 有值,现在暂时只支持一层子菜单。有需要再考虑完善。
  453. 上面数据的效果图:</p>
  454. <p><img src="access.jpg" alt="access.jpg" /><br></p>
  455. </body>
  456. </html>
  457. <!-- This document was created with MarkdownPad, the Markdown editor for Windows (http://markdownpad.com) -->