国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

springBoot+springSecurity 動態管理Restful風格權限(三)

2019-11-08 19:49:15
字體:
來源:轉載
供稿:網友

上一篇博客 sPRingBoot+springSecurity 數據庫動態管理用戶、角色、權限(二) 只是實現了用戶、角色、權限的動態管理,但是其權限管理是有缺陷的,他不支持restful風格的接口權限管理,因為他無法區分客戶端的請求方式。

本片博客是為了彌補此缺陷的,本篇博客將在 springBoot+springSecurity 數據庫動態管理用戶、角色、權限(二) 的基礎上進行修改使其支持 restful 風格的接口的權限管理。

本文目錄: 1. 分析工作量 2. 修改代碼 3. 準備數據 4. 測試


一、分析

首先分析一下工作量吧,因為要支持 restful 風格的接口,那么我們在判斷用戶是不是有權限訪問的時候不僅要判斷 url 還要判斷 請求方式。 所以我門需要修改數據庫表,因為我門的權限表還沒有method 字段。

由于要判斷 url 和 method 所以要在CustomUserService 類的 loadUserByUsername 方法中要添加 權限的 url 和 method 。但是SimpleGrantedAuthority 只支持傳入一個參數。 所以我門考慮要再寫一個類 實現 GrantedAuthority 接口,并在構造函數中傳入兩個參數。嘻嘻。

由于我們不僅要判斷url 還要 判斷請求方法,所以當然要修改 MyaccessDecisionManager 的decide 方法的內容了。因為:decide 方法是判定是否擁有權限的決策方法 ,三個參數的含義分別為: //authentication 是釋CustomUserService中循環添加到 GrantedAuthority 對象中的權限信息集合. //object 包含客戶端發起的請求的requset信息,可轉換為 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); //configAttributes 為MyInvocationSecurityMetadataSource的getAttributes(Object object)這個方法返回的結果,此方法是為了判定用戶請求的url 是否在權限表中,如果在權限表中,則返回給 decide 方法,用來判定用戶是否有此權限。如果不在權限表中則放行。當然在 修改一下 MyInvocationSecurityMetadataSourceService 的getAttributes 方法。//此方法是為了判定用戶請求的url 是否在權限表中,如果在權限表中,則返回給 decide 方法,用來判定用戶是否有此權限。如果不在權限表中則放行。 //因為我不想每一次來了請求,都先要匹配一下權限表中的信息是不是包含此url,我準備直接攔截,不管請求的url 是什么都直接攔截,然后在MyAccessDecisionManager的decide 方法中做 攔截還是放行的決策。

5.關閉csrf 6.添加restful 風格的接口

好了分析完了,接下來就是編碼了。


二、 修改

1. 修改permission表

添加method 字段,當然Permission 的java bean 中 也要添加此屬性和其get set方法。

這里寫圖片描述

//請求方法 private String method; public String getMethod() { return method; } public void setMethod(String method) { this.method = method; }

2. 實現 GrantedAuthority 接口

新建java類MyGrantedAuthority 實現 GrantedAuthority 接口

package com.us.example.service;import org.springframework.security.core.GrantedAuthority;/** * Created by yangyibo on 17/2/15. */public class MyGrantedAuthority implements GrantedAuthority { private String url; private String method; public String getPermissionUrl() { return url; } public void setPermissionUrl(String permissionUrl) { this.url = permissionUrl; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public MyGrantedAuthority(String url, String method) { this.url = url; this.method = method; } @Override public String getAuthority() { return this.url + ";" + this.method; }}

在CustomUserService 類中使用MyGrantedAuthority

public UserDetails loadUserByUsername(String username) { SysUser user = userDao.findByUserName(username); if (user != null) { List<Permission> permissions = permissionDao.findByAdminUserId(user.getId()); List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); for (Permission permission : permissions) { if (permission != null && permission.getName() != null) { GrantedAuthority grantedAuthority = new MyGrantedAuthority(permission.getUrl(), permission.getMethod()); grantedAuthorities.add(grantedAuthority); } } return new User(user.getUsername(), user.getPassWord(), grantedAuthorities); } else { throw new UsernameNotFoundException("admin: " + username + " do not exist!"); } }

3.修改 MyAccessDecisionManager 的decide 方法

package com.us.example.service;import org.springframework.security.access.AccessDecisionManager;import org.springframework.security.access.AccessDeniedException;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.authentication.InsufficientAuthenticationException;import org.springframework.security.core.Authentication;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.web.FilterInvocation;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletRequest;import java.util.Collection;import java.util.Iterator;/** * Created by yangyibo on 17/1/19. */@Servicepublic class MyAccessDecisionManager implements AccessDecisionManager { //decide 方法是判定是否擁有權限的決策方法 @Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); String url, method; AntPathRequestMatcher matcher; for (GrantedAuthority ga : authentication.getAuthorities()) { if (ga instanceof MyGrantedAuthority) { MyGrantedAuthority urlGrantedAuthority = (MyGrantedAuthority) ga; url = urlGrantedAuthority.getPermissionUrl(); method = urlGrantedAuthority.getMethod(); matcher = new AntPathRequestMatcher(url); if (matcher.matches(request)) { //當權限表權限的method為ALL時表示擁有此路徑的所有請求方式權利。 if (method.equals(request.getMethod()) || "ALL".equals(method)) { return; } } } else if (ga.getAuthority().equals("ROLE_ANONYMOUS")) {//未登錄只允許訪問 login 頁面 matcher = new AntPathRequestMatcher("/login"); if (matcher.matches(request)) { return; } } } throw new AccessDeniedException("no right"); } @Override public boolean supports(ConfigAttribute attribute) { return true; } @Override public boolean supports(Class<?> clazz) { return true; }}

4. 修改MyInvocationSecurityMetadataSourceService 的getAttributes 方法

package com.us.example.service;import com.us.example.dao.PermissionDao;import com.us.example.domain.Permission;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.access.SecurityConfig;import org.springframework.security.web.FilterInvocation;import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;import org.springframework.security.web.util.matcher.AntPathRequestMatcher;import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletRequest;import java.util.*;/** * Created by yangyibo on 17/1/19. */@Servicepublic class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource { //此方法是為了判定用戶請求的url 是否在權限表中,如果在權限表中,則返回給 decide 方法,用來判定用戶是否有此權限。如果不在權限表中則放行。 //因為我不想每一次來了請求,都先要匹配一下權限表中的信息是不是包含此url, // 我準備直接攔截,不管請求的url 是什么都直接攔截,然后在MyAccessDecisionManager的decide 方法中做攔截還是放行的決策。 //所以此方法的返回值不能返回 null 此處我就隨便返回一下。 @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { Collection<ConfigAttribute> co=new ArrayList<>(); co.add(new SecurityConfig("null")); return co; } @Override public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } @Override public boolean supports(Class<?> clazz) { return true; }}

5.關閉csrf

關于 什么是csrf 請看我的這篇博客

spring security CSRF 問題

修改 WebSecurityConfig 的configure(HttpSecurity http) 方法 ,添加 .csrf().disable();

@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() //任何請求,登錄后可以訪問 .and() .formLogin() .loginPage("/login") .failureUrl("/login?error") .permitAll() //登錄頁面用戶任意訪問 .and() .logout().permitAll(); //注銷行為任意訪問 http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class) .csrf().disable(); }

6. 修改HomeController

由于我們是要測試restful 風格的權限,所以我門要有restful 的接口

package com.us.example.controller;import com.us.example.domain.Msg;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.ResponseBody;/** * Created by yangyibo on 17/1/18. */@Controllerpublic class HomeController { @RequestMapping("/") public String index(Model model){ Msg msg = new Msg("測試標題","測試內容","歡迎來到HOME頁面,您擁有 ROLE_HOME 權限"); model.addAttribute("msg", msg); return "home"; } @RequestMapping("/admin") @ResponseBody public String hello(){ return "hello admin"; } @RequestMapping("/login") public String login(){ return "login"; } @RequestMapping(value = "/user", method = RequestMethod.GET) @ResponseBody public String getList(){ return "hello getList"; } @RequestMapping(value = "/user", method = RequestMethod.POST) @ResponseBody public String save(){ return "hello save"; } @RequestMapping(value = "/user", method = RequestMethod.PUT) @ResponseBody public String update(){ return "hello update"; }}

好了編碼部分完成了

三、準備數據

在數據庫中添加測試數據,主要是權限表和權限角色中間表。

結果(角色1 可以訪問 /user 下的所有接口, 角色2 只可以訪問 /user 下的GET請求)

權限表: 這里寫圖片描述

權限角色中間表:(此處角色1擁有 權限 6 ,權限6的方法為 ALL 也就是角色6 可以訪問所有路徑為/user 的接口) 這里寫圖片描述


四、測試

啟動項目,然后在postman 中測試, 1. 登錄admin 后訪問 user 的所有權限,都可以正常訪問。 這里寫圖片描述

這里寫圖片描述

這里寫圖片描述

put 方法訪問成功 。

登錄abel 后訪問 user 的所有權限,只有GET 權限可以訪問。

這里寫圖片描述

這里寫圖片描述

這里寫圖片描述

put 方法訪問失敗。


半夜碼字。。。 如果本文對您有幫助請給個好評,謝謝。

本文源碼:https://github.com/527515025/springBoot

參考文獻: http://www.cnblogs.com/dongying/p/6106855.html http://www.cnblogs.com/dongying/p/6128268.html


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 滨海县| 定日县| 光山县| 东乡族自治县| 时尚| 利川市| 涞源县| 清新县| 永年县| 榆社县| 政和县| 大化| 金平| 冷水江市| 红桥区| 金平| 普格县| 绥化市| 西宁市| 博野县| 杭锦旗| 彭水| 涡阳县| 沂南县| 大邑县| 新蔡县| 云阳县| 大田县| 泰州市| 桂平市| 鸡西市| 阳朔县| 邹平县| 九江市| 镇康县| 鄂伦春自治旗| 新疆| 弥渡县| 洱源县| 乐都县| 兴城市|