SpringSecurity概念及整合ssm框架的示例詳解
基本概念
Spring中提供安全認證服務的框架,認證:驗證用戶密碼是否正確的過程,授權:對用戶能訪問的資源進行控制
用戶登錄系統(tǒng)時我們協(xié)助 SpringSecurity 把用戶對應的角色、權限組裝好,同時把各個資源所要求的權限信息設定好,剩下的“登錄驗證”、“權限驗證”等等工作都交給SpringSecurity。
權限管理過程中的相關概念
主體
英文單詞:principal
使用系統(tǒng)的用戶或設備或從其他系統(tǒng)遠程登錄的用戶等等。簡單說就是誰使用系統(tǒng)誰就是主體。
認證
英文單詞:authentication
權限管理系統(tǒng)確認一個主體的身份,允許主體進入系統(tǒng)。簡單說就是“主體”證明自己是誰?;\統(tǒng)的認為就是以前所做的登錄操作。
授權
英文單詞:authorization
將操作系統(tǒng)的“權力”“授予”“主體”,這樣主體就具備了操作系統(tǒng)中特定功能的能力。
所以簡單來說,授權就是給用戶分配權限。
使用
pom文件中加入spring security的依賴
<!-- SpringSecurity 對 Web 應用進行權限管理 --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.2.10.RELEASE</version> </dependency> <!-- SpringSecurity 配置 --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.2.10.RELEASE</version> </dependency> <!-- SpringSecurity 標簽庫 --> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>4.2.10.RELEASE</version> </dependency>
web.xml加入SpringSecurity控制權限的Filte
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
加入配置類
package com.atguigu.crowd.mvc.config; import com.atguigu.crowd.constant.CrowdConstant; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.access.AccessDeniedHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Configuration// 表示當前類是一個配置類 @EnableWebSecurity// 啟用web環(huán)境下權限控制 // prePostEnabled = true的作用:保證@PreAuthorize、@PreAuthorize、@PreFilter、@PostFilter生效 @EnableGlobalMethodSecurity(prePostEnabled = true)// 啟用全局方法權限控制 public class WebApplicationConfig extends WebSecurityConfigurerAdapter { @Autowired CrowdUserDetailsService crowdUserDetailsService; @Autowired BCryptPasswordEncoder passwordEncoder; @Override protected void configure(HttpSecurity security) throws Exception { security .authorizeRequests() .antMatchers("/admin/to/login/page.html") .permitAll()// 允許無條件訪問登錄請求 .antMatchers("/bootstrap/**", "/crowd/**", "/css/**", "/fonts/**", "/img/**", "/jquery/**", "/layer/**", "/script/**", "/ztree/**") .permitAll()// 允許無條件訪問靜態(tài)文件 .antMatchers("/admin/get/page.html") .hasAuthority("user:get") // 擁有user:get權限才可以訪問用戶維護 .antMatchers("/role/to/role/page.html") .hasRole("經(jīng)理")// 擁有經(jīng)理角色才可以訪問角色維護 .antMatchers("/admin/get/page.html") .access("(hasAnyRole('經(jīng)理')) and hasAuthority('user:get')") .anyRequest() .authenticated()// 其他任何資源都要登錄才可以訪問 .and() .exceptionHandling() .accessDeniedHandler(new AccessDeniedHandler() { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { request.setAttribute("exception", new Exception(CrowdConstant.MESSAGE_ACCESS_DENIED)); request.getRequestDispatcher("/WEB-INF/error/system_error.jsp").forward(request, response); } })// 出現(xiàn)異常的處理方法 .and() .csrf() .disable()// 禁用跨站請求偽造功能 .formLogin()// 開啟表單登錄功能 .loginPage("/admin/to/login/page.html")// 設置默認的登錄頁面 .loginProcessingUrl("/security/do/login.html")// 處理登錄請求的地址 .defaultSuccessUrl("/admin/to/admin-main/page.html")// 登錄成功后要前往的地址 .usernameParameter("loginAcct")// 賬號的請求參數(shù)名 .passwordParameter("userPswd")// 密碼的請求參數(shù)名 .and() .logout() .logoutUrl("/security/do/logout.html")// 退出登錄訪問的地址 .logoutSuccessUrl("/admin/to/login/page.html")// 退出頁面成功要去的地址 ; } @Override protected void configure(AuthenticationManagerBuilder builder) throws Exception { // builder // .inMemoryAuthentication()// 開啟內(nèi)存認證 // .withUser("tom")// 設置賬號 // .password("123123")// 設置密碼 // .roles("ADMIN")// 設置角色 // ; // 使用基于數(shù)據(jù)庫的認證 builder.userDetailsService(crowdUserDetailsService).passwordEncoder(passwordEncoder); } }
注解@PreAuthorize規(guī)定角色權限
需要在SpringSecurity中標注
@EnableGlobalMethodSecurity(prePostEnabled = true)
/** * 根據(jù)關鍵字查詢分頁信息 * * @param pageNum 當前頁碼 * @param pageSize 每頁顯示條數(shù) * @param keyword 關鍵字 * @return 分頁信息 */ @PreAuthorize("hasAuthority('role:get') or hasAnyRole('經(jīng)理')")// 需要有role:get權限才可以訪問 @ResponseBody @GetMapping("/role/get/page/info.json") public ResultEntity<PageInfo<Role>> getPageInfo( @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum, @RequestParam(value = "pageSize", defaultValue = "4") Integer pageSize, @RequestParam(value = "keyword", defaultValue = "") String keyword ) { // 獲取頁面數(shù)據(jù) PageInfo<Role> pageInfo = roleService.getRoleByKeyword(pageNum, pageSize, keyword); // 如果出現(xiàn)異常,dispatcherServlet會進行處理 return ResultEntity.successWithData(pageInfo); }
@PostAuthorize
先執(zhí)行方法然后根據(jù)方法返回值判斷是否具備權限。
例如:查詢一個 Admin 對象,在@PostAuthorize 注解中和當前登錄的 Admin 對象進行比較,如果不一致,則判斷為不能訪問。實現(xiàn)“只能查自己”效果。
@PostAuthorize("returnObject.data.loginAcct == principal.username")
使用 returnObject 獲取到方法返回值,使用 principal 獲取到當前登錄用戶的主體對象。
通過故意寫錯表達式,然后從異常信息中發(fā)現(xiàn)表達式訪問的是下面這個類的屬性:
org.springframework.security.access.expression.method.MethodSecurityExpressionRoot
@PreFilter
在方法執(zhí)行前對傳入的參數(shù)進行過濾。只能對集合類型的數(shù)據(jù)進行過濾。
@PreFilter(value="filterObject%2==0") @ResponseBody @RequestMapping("/admin/test/pre/filter") public ResultEntity<List<Integer>> saveList(@RequestBody List<Integer> valueList) { return ResultEntity.successWithData(valueList); }
@PostFilter
在方法執(zhí)行后對方法返回值進行過濾。只能對集合類型的數(shù)據(jù)進行過濾。
CrowdUserDetailsService
其實返回的就是SpringSecurity的User對象,只是做了一層封裝。
package com.atguigu.crowd.mvc.config; import com.atguigu.crowd.entity.Admin; import com.atguigu.crowd.entity.Role; import com.atguigu.crowd.service.api.AdminService; import com.atguigu.crowd.service.api.AuthService; import com.atguigu.crowd.service.api.RoleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; @Component public class CrowdUserDetailsService implements UserDetailsService { @Autowired private AdminService adminService; @Autowired private RoleService roleService; @Autowired private AuthService authService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1、根據(jù)賬號名稱查找Admin對象 Admin admin = adminService.getAdminByLoginAcct(username); // 2、獲取adminId Integer adminId = admin.getId(); // 3、根據(jù)adminId查詢角色信息 List<Role> roles = roleService.getAssignedRole(adminId); // 4、根據(jù)adminId查詢權限名字信息 List<String> auths = authService.getAssignedAuthNameByAdminId(adminId); // 5、創(chuàng)建集合對象來存儲GrantedAuthority ArrayList<GrantedAuthority> authorities = new ArrayList<>(); // 6、遍歷存入角色消息 for (int i = 0; i < roles.size(); i++) { // 需要加前綴,因為SpringSecurity就是通過ROLE_來區(qū)分是角色還是權限 String roleName = "ROLE_" + roles.get(i).getName(); SimpleGrantedAuthority authority = new SimpleGrantedAuthority(roleName); authorities.add(authority); } // 7、遍歷存入權限信息 for (int i = 0; i < auths.size(); i++) { String authName = auths.get(i); SimpleGrantedAuthority authority = new SimpleGrantedAuthority(authName); authorities.add(authority); } // 8、封裝到SecurityAdmin對象中,它繼承了SpringSecurity的User類 SecurityAdmin securityAdmin = new SecurityAdmin(admin, authorities); return securityAdmin; } }
BCryptPasswordEncoder
它是SpringSecurity自帶的密碼加密與驗證的類。
頁面元素控制
取出當前登錄對象
<%--需要導入taglib--%> <%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %> <%--principal 是我們自己封裝的 SecurityAdmin 對象(返回的SpringSecurity的User對象)--%> <security:authentication property="principal.originalAdmin.userName"/>
標簽庫控制
<%--需要導入taglib--%> <%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %> <security:authorize access="hasRole('經(jīng)理')"> <!-- 開始和結束標簽之間是要進行權限控制的部分。檢測當前用戶是否有權限,有權限 就顯示這里的內(nèi)容,沒有權限就不顯示。 --> …… </security:authorize>
access屬性可以傳入權限控制相關的表達式。
### 標簽庫控制 ```html <%--需要導入taglib--%> <%@ taglib uri="http://www.springframework.org/security/tags" prefix="security" %> <security:authorize access="hasRole('經(jīng)理')"> <!-- 開始和結束標簽之間是要進行權限控制的部分。檢測當前用戶是否有權限,有權限 就顯示這里的內(nèi)容,沒有權限就不顯示。 --> …… </security:authorize>
access屬性可以傳入權限控制相關的表達式。
到此這篇關于SpringSecurity概念以及整合ssm框架的文章就介紹到這了,更多相關SpringSecurity整合ssm框架內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot啟動加載CommandLineRunner @PostConstruct問題
這篇文章主要介紹了springboot啟動加載CommandLineRunner @PostConstruct問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08Spring IOC簡單理解及創(chuàng)建對象的方式
這篇文章主要介紹了Spring IOC簡單理解及創(chuàng)建對象的方式,本文通過兩種方式給大家介紹創(chuàng)建對象的方法,通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2021-09-09JAVA中JSONObject對象和Map對象之間的相互轉(zhuǎn)換
這篇文章主要介紹了JAVA中JSONObject對象和Map對象之間的相互轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01MybatisPlus 不修改全局策略和字段注解如何將字段更新為null
這篇文章主要介紹了MybatisPlus 不修改全局策略和字段注解如何將字段更新為null,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04java Socket實現(xiàn)簡單模擬HTTP服務器
這篇文章主要介紹了java Socket實現(xiàn)簡單模擬HTTP服務器,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05