SpringSecurity深度解析與實踐(3)

這里寫自定義目錄標題

  • 引言
  • SpringSecurity之授權
    • 授權介紹
    • java權限集成
  • 登錄失敗三次用戶上鎖

在這里插入圖片描述

引言

SpringSecurity深度解析與實踐(2)的網址

SpringSecurity之授權

授權介紹

Spring Security 中的授權分為兩種類型:

  • 基于角色的授權:以用戶所屬角色為基礎進行授權,如管理員、普通用戶等,通過為用戶分配角色來控制其對資源的訪問權限。
  • 基于資源的授權:以資源為基礎進行授權,如 URL、方法等,通過定義資源所需的權限,來控制對該資源的訪問權限。

Spring Security 提供了多種實現授權的機制,最常用的是使用基于注解的方式,建立起訪問資源和權限之間的映射關系。

其中最常用的兩個注解是 @Secured@PreAuthorize@Secured 注解是更早的注解,基于角色的授權比較適用,@PreAuthorize 基于 SpEL 表達式的方式,可靈活定義所需的權限,通常用于基于資源的授權。

java權限集成

WebSecurityConfig配置類

package com.yuan.springsecurity1.config;import com.fasterxml.jackson.databind.ObjectMapper;
import com.yuan.springsecurity1.resp.JsonResponseBody;
import com.yuan.springsecurity1.resp.JsonResponseStatus;
import com.yuan.springsecurity1.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;import javax.sql.DataSource;@Configuration
//開啟SpringSecurity的默認行為
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Autowiredprivate DataSource dataSource;/*** 配置持久化Token方式,注意tokenRepository.setCreateTableOnStartup()配置*/@Beanpublic PersistentTokenRepository persistentTokenRepository(){JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();tokenRepository.setDataSource(dataSource);// 設置為true要保障數據庫該表不存在,不然會報異常哦// 所以第二次打開服務器應用程序的時候得把它設為falsetokenRepository.setCreateTableOnStartup(false);return tokenRepository;}@Autowiredprivate MyUserDetailsService myUserDetailsService;@AutowiredObjectMapper objectMapper;@AutowiredMyAuthenticationFailureHandler myAuthenticationFailureHandler;/*** 獲取AuthenticationManager(認證管理器),登錄時認證使用(基于數據庫方式)* @param* @return* @throws Exception*/@Beanpublic AuthenticationManager authenticationManager() throws Exception {//創建DaoAuthenticationProviderDaoAuthenticationProvider provider=new DaoAuthenticationProvider();//設置userDetailsService,基于數據庫方式進行身份認證provider.setUserDetailsService(myUserDetailsService);//配置密碼編碼器provider.setPasswordEncoder(passwordEncoder());return new ProviderManager(provider);}@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{http.authorizeRequests()// 開放接口訪問權限,不需要登錄就可以訪問.antMatchers("/toLogin").permitAll()//訪問路徑有admin的方法時,需要有ADMIN的身份
//                    .antMatchers("/admin/**").hasRole("ADMIN")
//                    .antMatchers("/user/**").hasAnyRole("ADMIN","USER")// 其余所有請求全部需要鑒權認證.anyRequest().authenticated().and().formLogin()// 設置登錄頁面的 URL.loginPage("/toLogin")// 設置登錄請求的 URL,即表單提交的 URL.loginProcessingUrl("/userLogin")// 設置登錄表單中用戶名字段的參數名,默認為username.usernameParameter("username")// 設置登錄表單中密碼字段的參數名,默認為password.passwordParameter("password")//成功后的處理.successHandler((req,resp,auth)->{
//                    resp.sendRedirect("/index");Object user = auth.getPrincipal();objectMapper.writeValue(resp.getOutputStream(), JsonResponseBody.success(user));})//登錄失敗的處理.failureHandler(myAuthenticationFailureHandler).and().exceptionHandling()
//                .accessDeniedPage("/noAccess")//權限不夠處理.accessDeniedHandler((req,resp,ex)->{objectMapper.writeValue(resp.getOutputStream(),JsonResponseBody.other(JsonResponseStatus.NO_ACCESS));})//沒有認證(登錄)處理.authenticationEntryPoint((req,resp,ex)->{objectMapper.writeValue(resp.getOutputStream(),JsonResponseBody.other(JsonResponseStatus.NO_LOGIN));}).and().logout()// 設置安全退出的URL路徑.logoutUrl("/logout")// 設置退出成功后跳轉的路徑.logoutSuccessUrl("/toLogin").and().rememberMe()// 指定 rememberMe 的參數名,用于在表單中攜帶 rememberMe 的值。.rememberMeParameter("remember-me")// 指定 rememberMe 的有效期,單位為秒,默認2周。.tokenValiditySeconds(600)// 指定 rememberMe 的 cookie 名稱。.rememberMeCookieName("remember-me-cookie")// 指定 rememberMe 的 token 存儲方式,可以使用默認的 PersistentTokenRepository 或自定義的實現。.tokenRepository(persistentTokenRepository())// 指定 rememberMe 的認證方式,需要實現 UserDetailsService 接口,并在其中查詢用戶信息。.userDetailsService(myUserDetailsService);
//        http.csrf().disable();return http.build();}
}

登錄權限綁定

package com.yuan.springsecurity1.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.yuan.springsecurity1.pojo.*;
import com.yuan.springsecurity1.mapper.UserMapper;
import com.yuan.springsecurity1.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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 org.springframework.stereotype.Service;import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;/*** <p>* 用戶信息表 服務實現類* </p>** @author yuan* @since 2023-12-21*/
@Component
public class MyUserDetailsService implements  UserDetailsService {@Autowiredprivate IUserService iUserService;@Autowiredprivate IUserRoleService iUserRoleService;@Autowiredprivate IRoleService iRoleService;@Autowiredprivate IRoleModuleService iRoleModuleService;@Autowiredprivate IModuleService iModuleService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = iUserService.getOne(new QueryWrapper<User>().eq("username", username));if(user==null)throw new UsernameNotFoundException("用戶名無效");//查詢所有的身份,map 遍歷數據對象,返回的數據放到一個新的流中,collect(Collectors.toList())用list集合接收List<Integer> userIds = iUserRoleService.list(new QueryWrapper<UserRole>().eq("user_id", user.getId())).stream().map(UserRole::getRoleId).collect(Collectors.toList());//根據role_id拿到身份名稱集合List<String> roleNames = iRoleService.list(new QueryWrapper<Role>().in("role_id", userIds)).stream().map(Role::getRoleName).collect(Collectors.toList());//根據身份id role_id拿到權限id module_idList<Integer> moduleIds = iRoleModuleService.list(new QueryWrapper<RoleModule>().in("role_id", userIds)).stream().map(RoleModule::getModuleId).collect(Collectors.toList());//根據權限id拿到對應的urlList<String> urls = iModuleService.list(new QueryWrapper<Module>().in("id", moduleIds)).stream().map(Module::getUrl).filter(Objects::nonNull).collect(Collectors.toList());roleNames.addAll(urls);List<SimpleGrantedAuthority> authorities = roleNames.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());user.setAuthorities(authorities);return user;}
}

Controller類數據

    @ResponseBody@RequestMapping("/o_f")@PreAuthorize("hasAnyAuthority('order:manager:analysis')")public String o_f() {return "訂單分析";}@ResponseBody@RequestMapping("/b_add")@PreAuthorize("hasAnyAuthority('book:manager:add')")public String b_add() {return "書籍新增";}

需要添加一個規則,判斷是否有權限,我這個放在WebSecurityConfig類上

@EnableGlobalMethodSecurity(prePostEnabled = true)

登錄失敗三次用戶上鎖

搭配WebSecurityConfig類中失敗的對象

package com.yuan.springsecurity1.config;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yuan.springsecurity1.pojo.User;
import com.yuan.springsecurity1.resp.JsonResponseBody;
import com.yuan.springsecurity1.resp.JsonResponseStatus;
import com.yuan.springsecurity1.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author 葉秋* @site* @company 卓京公司* @create 2023-12-23 23:21*/
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {@AutowiredObjectMapper objectMapper;@Autowiredprivate IUserService iUserService;@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {if(1==2){ //假設超過三次失敗User user = iUserService.getOne(new QueryWrapper<User>().eq("username", request.getParameter("username")));user.setAccountNonLocked(false);iUserService.updateById(user);}objectMapper.writeValue(response.getOutputStream(), JsonResponseBody.other(JsonResponseStatus.LOGIN_FAILURE));}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/454303.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/454303.shtml
英文地址,請注明出處:http://en.pswp.cn/news/454303.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

簡單解釋什么是 依賴注入 和 控制反轉

簡單解釋什么是 依賴注入 和 控制反轉2017-07-09 關于 依賴注入 與 控制反轉 的概念有些人覺得很難理解&#xff0c;最近在給別人講這個概念的時候梳理了一個比較好理解的解釋&#xff0c;而且我認為非技術人員也應該能聽的懂&#xff0c;因此分享給大家&#xff0c;希望下次你…

python pip install指定國內源鏡像

有時候安裝一些依賴包&#xff0c;網不好&#xff0c;直接超時&#xff0c;或者這個包就是死都下不下來的時候&#xff0c;可以指定國內源鏡像。 pip install -i 國內鏡像地址 包名 清華&#xff1a;https://pypi.tuna.tsinghua.edu.cn/simple 阿里云&#xff1a;http://mirr…

機器學習之單標簽多分類及多標簽多分類

單標簽二分類算法 Logistic算法 單標簽多分類算法 Softmax算法 One-Versus-One&#xff08;ovo&#xff09;&#xff1a;一對一 One-Versus-All / One-Versus-the-Rest&#xff08;ova/ovr&#xff09;&#xff1a; 一對多 ovo和ovr的區別 Error Correcting Output code…

ionic3 隱藏子頁面tabs

看了幾天ionic3 問題還挺多的&#xff0c;今天想把所有子頁面tabs 給去掉&#xff0c;整了半天&#xff0c;發現app.Module 是可以配置的 修改 IonicModule.forRoot(MyApp&#xff09; imports: [BrowserModule,// IonicModule.forRoot(MyApp),HttpModule,IonicModule.forRoot(…

cas單點登錄-jdbc認證(三)

前言 本節的內容為JDBC認證&#xff0c;查找數據庫進行驗證&#xff0c;其中包括&#xff1a; 密碼加密策略&#xff08;無密碼&#xff0c;簡單加密&#xff0c;加鹽處理&#xff09;認證策略&#xff08;jdbc&#xff09;一、業務需求 不同的公司&#xff0c;需求業務需求或者…

get clone 出現 fatal: the remote end hung up unexpectedly5 MiB | 892.00 KiB/s 報錯信息

fatal: the remote end hung up unexpectedly5 MiB | 892.00 KiB/s 解決方案 &#xff08;親測有效&#xff09; 解決方案如下&#xff1a; git clone時加上 --depth1&#xff0c;比如&#xff1a; git clone https://gitee.com/songyitian/tctm.git --depth 1depth用于指定…

mybatis foreach map_重學Mybatis(六)-------輸入映射(含面試題)

博主將會針對Java面試題寫一組文章&#xff0c;包括J2ee&#xff0c;SQL&#xff0c;主流Web框架&#xff0c;中間件等面試過程中面試官經常問的問題&#xff0c;歡迎大家關注。一起學習&#xff0c;一起成長&#xff0c;文章底部有面試題。入參映射關鍵字說明圖中paramenterTy…

php輸出多余的空格或者空行

1&#xff0c;文件是否有bom。可以通過腳步檢測&#xff0c;或者利用notepa打開&#xff0c;查看編碼格式。 2. <?php echo something; ?> 或許是你的php標簽外&#xff0c;有空格或者空行。一般的項目都是用框架&#xff0c;包含很多的文件&#xff0c;如果一個個文…

執行git命令時出現fatal: ‘origin‘ does not appear to be a git repository錯誤

執行git命令時出現fatal: ‘origin’ does not appear to be a git repository錯誤 在執行git pull origin master時出現&#xff1a;   fatal: ‘origin’ does not appear to be a git repository   致命提示:“origin”看起來不是一個git存儲庫   fatal: Could not r…

蔣濤作序盛贊Leo新作為“程序員職場實用百科全書”——《程序員羊皮卷》連載(1)

《程序員羊皮卷》當當購買地址&#xff1a;http://product.dangdang.com/product.aspx?product_id20691986 互動購買地址&#xff1a;http://www.china-pub.com/196049 程序員行業從外面看起來有很多絢麗的光環&#xff0c;這里有無數以程序致富的天才&#xff0c;世界首富比…

matlab ones函數_Matlab中相見恨晚的命令(持續更新)

知乎上有個“有哪些讓人相見恨晚的Matlab命令”的話題&#xff0c;很多答主提供的命令確實很實用&#xff0c;為了更方便大家的學習&#xff0c;我就知乎上的答案和我自己想到的都綜合整理成了一篇文章&#xff0c;把我覺得很實用的指令整理出來。知乎原答案鏈接dbstop if erro…

機器學習之特征工程

特征工程-概念 特征工程是一個面向十分廣的概念&#xff0c;只要是在處理數據就可以認為是在做特征工程。個人理解&#xff0c;真正意義上的特征工程還是數據降維和數據升維的過程。 而前期對數據的處理過程&#xff1a; 需要哪些數據&#xff1f;數據如何存儲&#xff1f;數…

ArcGIS AO開發高亮顯示某些要素

參考代碼1 ifeaturecursor pcur ifeatureclass.search(iqueryfilter pfilter); pfilter.whereclause strAddress; //輸入查詢條件&#xff0c;也就是你寸地址的字段名didian ifeature pfeat pcur.nextfeature();// 如果pCur多個要素&#xff0c;則可以考慮將其合并并一起高亮…

Oracle傳輸表空間介紹

傳輸表空間通過拷貝數據文件的方式&#xff0c;實現可跨平臺的數據遷移&#xff0c;效率遠超expdp/impdp, exp/imp等工具。還可以應用跨平臺&數據庫版本遷移表數據、歸檔歷史數據和實現表空間級時間點數據恢復等場景。轉載于:https://www.cnblogs.com/ilifeilong/p/7712654…

git push到GitHub的時候遇到! [rejected] master -> master (non-fast-forward)的問題

git push到GitHub的時候遇到! [rejected] master -> master (non-fast-forward)的問題 解決方法&#xff1a; 1、git pull origin master --allow-unrelated-histories //把遠程倉庫和本地同步&#xff0c;消除差異 2、重新add和commit相應文件 3、git push origin maste…

程序員考核的五大死因(上)

程序員作為企業開發力量的最核心資產&#xff0c;無疑得到公司從上至下的一致關注。開發是個智力密集型產業&#xff0c;程序開發的特點是&#xff0c;付出相同時間的情況下&#xff0c;兩個開發者之間的產能會相差十幾甚至幾十倍。軟件開發人員向來以“不容易考核、工作不容易…

du -sh 如何找到最大的文件夾_小白必看!手把手教你如何在linux上安裝redis數據庫...

首先我們要清楚redis是什么&#xff1f;redis是一種非關系型數據庫&#xff0c;它與MySQL的這種關系型數據庫不同&#xff0c;MySQL是將數據存儲在磁盤中&#xff0c;而redis是儲存在內存中。一般很多公司都是使用MySQLredis兩種數據存儲方式&#xff0c;這樣可以提高性能&…

Linux刪除特殊字符文件

1.刪除帶“-”的文件名的方法使用-- &#xff08;2個橫杠&#xff09;#touch -- -%F-%T#rm -- -%F-%Trm: remove regular empty file -%F-%T?使用絕對路徑并TAB特殊文件名#rm /root/-%F-%Trm: remove regular empty file /root/-%F-%T?2. 刪除包含其它特殊字符的文件對于含有…

機器學習之線性回歸 損失函數、代價函數、目標函數

損失函數&#xff08;Loss Function&#xff09;定義在單個樣本上&#xff0c;算的是一個樣本的誤差。比如&#xff1a; 其中0-1損失函數: 感知器損失函數&#xff1a; 平方和損失函數&#xff1a; 絕對損失函數&#xff1a; 對數損失函數&#xff1a; 代價函數&#xff08;Cos…

bzoj4950(二分圖最大匹配)

[Wf2017]Mission Improbable Time Limit: 1 Sec Memory Limit: 1024 MBSubmit: 105 Solved: 49[Submit][Status][Discuss]Description 那是春日里一個天氣晴朗的好日子,你準備去見見你的老朋友Patrick,也是你之前的犯罪同伙。Patrick在編程競賽上豪賭輸掉了一大筆錢,所以他需…