<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot整合SpringSecurity(附源碼)

          共 11709字,需瀏覽 24分鐘

           ·

          2020-10-24 05:30

          點擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達(dá)

          66套java從入門到精通實戰(zhàn)課程分享

          在前幾篇博客里,我們對于SpringBoot框架的項目中的認(rèn)證還是采用最樸素的攔截器來實現(xiàn)的,那SpringBoot這么高級,就沒有什么成熟的解決方案嗎?有的,Spring Security,今天我們就來認(rèn)識Spring Security,再配上一個demo加深理解。

          Spring Security簡介

          Spring Security 是針對Spring項目的安全框架,也是Spring Boot底層安全模塊默認(rèn)的技術(shù)選型,他可以實現(xiàn)強大的Web安全控制,對于安全控制,我們僅需要引入?spring-boot-starter-security?模塊,進(jìn)行少量的配置,即可實現(xiàn)強大的安全管理。

          記住常用的幾個類:

          • WebSecurityConfigurerAdapter:自定義 Security 策略

          • AuthenticationManagerBuilder:自定義認(rèn)證策略

          • @EnableWebSecurity:開啟 WebSecurity 模式

          Spring Security的兩個主要目標(biāo)是 “認(rèn)證” 和 “授權(quán)”(訪問控制)。

          “認(rèn)證”(Authentication)

          身份驗證是關(guān)于驗證您的憑據(jù),如用戶名/用戶ID和密碼,以驗證您的身份。

          身份驗證通常通過用戶名和密碼完成,有時與身份驗證因素結(jié)合使用。

          “授權(quán)” (Authorization)

          授權(quán)發(fā)生在系統(tǒng)成功驗證您的身份后,最終會授予您訪問資源(如信息,文件,數(shù)據(jù)庫,資金,位置,幾乎任何內(nèi)容)的完全權(quán)限。

          那實際上除了SpringSecurity,用的比較多的安全框架還有shiro。可以下宏觀的了解一下

          SpringSecurity和Shiro的相同點和不同點。

          • 相同點

          認(rèn)證功能、授權(quán)功能、加密功能、會話管理、緩存支持、rememberMe功能

          • 不同點

          1、SpringSecurity基于Spring開發(fā),項目中如果使用Spring作為基礎(chǔ),配合SpringSecurity做權(quán)限更加方便,而Shiro需要和Spring進(jìn)行整合開發(fā)

          2、SpringSecurity功能比Shiro更加豐富些,例如安全防護(hù)

          3、SpringSecurity社區(qū)資源比Shiro豐富

          4、Shiro配置和使用比較簡單,SpringSecurity上手復(fù)雜

          5、Shiro依賴性低,不需要任何框架和容器,可以獨立運行,而SpringSecurity依賴于Spring容器。

          測試Demo

          前置準(zhǔn)備

          首先創(chuàng)建一個SpringBoot項目,勾選SpringSecurity模塊

          或者創(chuàng)建項目后導(dǎo)入依賴


          ???org.springframework.boot
          ???spring-boot-starter-security


          為了方便前端展示,我們還導(dǎo)入thymeleaf依賴

          創(chuàng)建幾個前端頁面(用于后面來測試權(quán)限訪問)提取碼:o9dz

          項目結(jié)構(gòu)如下圖所示

          測試主頁及跳轉(zhuǎn)(測試時先把SpringSecurity依賴注釋掉

          編寫基礎(chǔ)配置類

          在項目下創(chuàng)建config包,新建SecurityConfig.java

          package?com.feng.config;

          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;

          /**
          ?*?

          springsecurity-test


          ?*?


          ?*
          ?*?@author?:?Nicer_feng
          ?*?@date?:?2020-10-13?11:38
          ?**/
          @EnableWebSecurity??//開啟WebSecurity模式
          public?class?SecurityConfig?extends?WebSecurityConfigurerAdapter?{

          ?????//?授權(quán)規(guī)則
          ????@Override
          ????protected?void?configure(HttpSecurity?http)?throws?Exception?{
          ????????//?首頁所有人可以訪問
          ????????//?其他界面只有對應(yīng)的角色(權(quán)限)才可以訪問
          ????????http.authorizeRequests().antMatchers("/").permitAll()
          ????????????????.antMatchers("/level1/**").hasRole("vip1")
          ????????????????.antMatchers("/level2/**").hasRole("vip2")
          ????????????????.antMatchers("/level3/**").hasRole("vip3");
          ????}
          }

          測試

          開啟后我們再測試下

          可以發(fā)現(xiàn)報了403forbidden錯誤

          There?was?an?unexpected?error?(type=Forbidden,?status=403).
          Access?Denied

          我們在配置類中添加如未登錄強制跳轉(zhuǎn)到login頁面

          這里的http.formLogin();表示開啟自動配置的登錄功能,如果無權(quán)限則跳轉(zhuǎn)到/login

          測試發(fā)現(xiàn)確實如此,如果沒有權(quán)限則強制跳轉(zhuǎn)到登錄頁面

          但需要注意的是,這個登錄頁面并不是我們自己寫的login頁面,而是SpringSecurity自帶的默認(rèn)登錄頁面

          重寫認(rèn)證規(guī)則

          我們可以自定義認(rèn)證規(guī)則,重寫configure(AuthenticationManagerBuilder auth)方法來配置認(rèn)證的規(guī)則。

          可以看到這里的認(rèn)證規(guī)則常用的有這幾種,這里先用inMemoryAuthentication(內(nèi)存數(shù)據(jù)庫)的來演示

          添加配置代碼

          package?com.feng.config;

          import?org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
          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;

          /**
          ?*?

          springsecurity-test


          ?*?


          ?*
          ?*?@author?:?Nicer_feng
          ?*?@date?:?2020-10-13?11:38
          ?**/
          @EnableWebSecurity??//開啟WebSecurity模式
          public?class?SecurityConfig?extends?WebSecurityConfigurerAdapter?{

          ????@Override
          ????protected?void?configure(AuthenticationManagerBuilder?auth)?throws?Exception?{
          ????????auth.inMemoryAuthentication()
          ????????????????.withUser("feng").password("111111").roles("vip1")
          ????????????????.and()
          ????????????????.withUser("user").password("22222").roles("vip2")
          ????????????????.and()
          ????????????????.withUser("admin").password("000000")
          ????????????????.roles("vip1","vip2","vip3");
          ????}

          ????@Override
          ????protected?void?configure(HttpSecurity?http)?throws?Exception?{
          ????????http.authorizeRequests().antMatchers("/").permitAll()
          ????????????????.antMatchers("/level1/**").hasRole("vip1")
          ????????????????.antMatchers("/level2/**").hasRole("vip2")
          ????????????????.antMatchers("/level3/**").hasRole("vip3");

          ????????http.formLogin();
          ????}
          }

          我們添加了三個用戶,分別擁有不同的權(quán)限,重啟tomcat后測試

          可以發(fā)現(xiàn)這里報了無id映射的錯誤,之所以報這個錯是因為從前端傳過來的密碼需要進(jìn)行加密,否則無法登陸,我們是用官方推薦的bcrypt加密方式

          ????@Override
          ????????protected?void?configure(AuthenticationManagerBuilder?auth)?throws?Exception?{
          ????????????auth.inMemoryAuthentication().passwordEncoder(new?BCryptPasswordEncoder())
          ????????????????????.withUser("feng").password(new?BCryptPasswordEncoder().encode("111111"))
          ????????????????????.roles("vip1")
          ????????????????????.and()
          ????????????????????.withUser("user").password(new?BCryptPasswordEncoder().encode("222222"))
          ????????????????????.roles("vip2")
          ????????????????????.and()
          ????????????????????.withUser("admin").password(new?BCryptPasswordEncoder().encode("000000"))
          ????????????????????.roles("vip1","vip2","vip3");
          ????????}

          重啟測試

          權(quán)限注銷

          在配置類中加入注銷功能

          @Override
          ????protected?void?configure(HttpSecurity?http)?throws?Exception?{
          ????????......

          ????????//開啟自動配置的注銷的功能
          ????????//?/logout?注銷請求
          ????????http.logout();
          ????}

          在index頁面添加logout注銷功能


          "right?menu">
          ????
          ????"item"?th:href="@{/login}">
          ????????"address?card?icon">?登錄
          ????
          ????
          ????"item"?th:href="@{/logout}">
          ????????"address?card?icon">?注銷
          ????


          注意這里的默認(rèn)提示中的/login和/logout都是SpringSecurity自帶的默認(rèn)界面

          點擊注銷后,會返回登錄界面

          如果想要注銷后仍然回到首頁,可以在logout()后添加logoutSuccessUrl

          http.logout().logoutSuccessUrl("/");

          根據(jù)權(quán)限顯示不同頁面

          上面我們設(shè)置了三個用戶,擁有不同權(quán)限,在實際業(yè)務(wù)中,那能不能讓擁有相應(yīng)權(quán)限的用戶只顯示相應(yīng)的界面呢?是可以做到的,我們需要利用thymeleaf 和SpringSecurity結(jié)合的功能

          首先添加對應(yīng)依賴


          ???org.thymeleaf.extras
          ???thymeleaf-extras-springsecurity5
          ???3.0.4.RELEASE


          修改前端的頁面

          頭部命名空間改為

          "en"?xmlns:th="http://www.thymeleaf.org"?xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">

          網(wǎng)頁部分

          "right?menu">
          ????
          ????"!isAuthenticated()">
          ????????"item"?th:href="@{/login}">
          ????????????"address?card?icon">?登錄
          ????????
          ????


          ????
          ????"isAuthenticated()">
          ????????"item">
          ????????????"address?card?icon">
          ????????????用戶名:"principal.username">
          ????????????角色:"principal.authorities">
          ????????
          ????


          ????"isAuthenticated()">
          ????????"item"?th:href="@{/logout}">
          ????????????"address?card?icon">?注銷
          ????????
          ????



          然后我們需要給相應(yīng)模塊附上相應(yīng)的權(quán)限等級

          "column"?sec:authorize="hasRole('vip1')">
          ???"ui?raised?segment">
          ???????"ui">
          ???????????"content">
          ???????????????"content">Level?1
          ???????????????

          ???????????????
          "@{/level1/1}">"bullhorn?icon">?Level-1-1

          ???????????????
          "@{/level1/2}">"bullhorn?icon">?Level-1-2

          ???????????????
          "@{/level1/3}">"bullhorn?icon">?Level-1-3

          ???????????
          ???????
          ???


          "column"?sec:authorize="hasRole('vip2')">
          ???"ui?raised?segment">
          ???????"ui">
          ???????????"content">
          ???????????????"content">Level?2
          ???????????????

          ???????????????
          "@{/level2/1}">"bullhorn?icon">?Level-2-1

          ???????????????
          "@{/level2/2}">"bullhorn?icon">?Level-2-2

          ???????????????
          "@{/level2/3}">"bullhorn?icon">?Level-2-3

          ???????????
          ???????
          ???


          "column"?sec:authorize="hasRole('vip3')">
          ???"ui?raised?segment">
          ???????"ui">
          ???????????"content">
          ???????????????"content">Level?3
          ???????????????

          ???????????????
          "@{/level3/1}">"bullhorn?icon">?Level-3-1

          ???????????????
          "@{/level3/2}">"bullhorn?icon">?Level-3-2

          ???????????????
          "@{/level3/3}">"bullhorn?icon">?Level-3-3

          ???????????
          ???????
          ???


          測試

          再次啟動測試

          可以看到我們做到“千人千面”了

          rememberMe

          在實際登錄中我們肯定有記住密碼這個狀態(tài),那在SpringSecurity中如何配置?十分簡單,只需要在授權(quán)規(guī)則內(nèi)加一行http.rememberMe()即可

          重啟測試下發(fā)現(xiàn)登錄頁面多了一個Remember me的選項

          打開瀏覽器的開發(fā)者工具發(fā)現(xiàn)該cookies信息保存14天

          并且如果我們點擊注銷,該cookies信息自動刪除

          定制登錄頁

          實際業(yè)務(wù)中顯然不可能使用SpringSecurity自帶的登錄界面,我們需要定制自己的登錄頁面,首先我們要在配置內(nèi)的登錄頁配置后添加指定的loginpage

          前端也需要指向我們自定義的登錄請求

          ???"item"?th:href="@{/toLogin}">
          ????????????????"address?card?icon">?登錄
          ???

          在login.html配置提交請求需要改成post

          "@{/login}"?method="post">
          ???"field">
          ???????
          ???????"ui?left?icon?input">
          ???????????type="text"?placeholder="Username"?name="username">
          ???????????"user?icon">
          ???????
          ???
          ???"field">
          ???????
          ???????"ui?left?icon?input">
          ???????????type="password"?name="password">
          ???????????"lock?icon">
          ???????
          ???
          ???type="submit"?class="ui?blue?submit?button"/>


          并且login.html增加記住我的選項框

          type="checkbox"?name="remember">?記住我

          加入這個功能時,配置類需要加入

          http.rememberMe().rememberMeParameter("remember");

          運行測試

          發(fā)現(xiàn)登錄都沒問題,但是注銷的時候缺出現(xiàn)了404錯誤,別緊張,是因為它默認(rèn)防止 csrf 跨站請求偽造,因為會產(chǎn)生安全問題,我們可以將請求改為 post 表單提交,或者在 Spring security 中關(guān)閉 csrf 功能。在授權(quán)配置中增加 http.csrf().disable() 即可

          再次運行即可

          彩蛋

          如果我們想用jdbc連數(shù)據(jù)庫來看認(rèn)證用戶呢(用戶信息存在數(shù)據(jù)庫中)

          首先在數(shù)據(jù)庫中創(chuàng)建一個用戶信息數(shù)據(jù)庫,這里直接貼sql

          /*
          SQLyog?Ultimate?v12.09?(64?bit)
          MySQL?-?5.7.23?:?Database?-?testspringsecurity
          *********************************************************************
          */


          /*!40101?SET?NAMES?utf8?*/;

          /*!40101?SET?SQL_MODE=''*/;

          /*!40014?SET?@OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS,?UNIQUE_CHECKS=0?*/;
          /*!40014?SET?@OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS,?FOREIGN_KEY_CHECKS=0?*/;
          /*!40101?SET?@OLD_SQL_MODE=@@SQL_MODE,?SQL_MODE='NO_AUTO_VALUE_ON_ZERO'?*/;
          /*!40111?SET?@OLD_SQL_NOTES=@@SQL_NOTES,?SQL_NOTES=0?*/;
          CREATE?DATABASE?/*!32312?IF?NOT?EXISTS*/`testspringsecurity`?/*!40100?DEFAULT?CHARACTER?SET?utf8?*/;

          USE?`testspringsecurity`;

          /*Table?structure?for?table?`authorities`?*/

          DROP?TABLE?IF?EXISTS?`authorities`;

          CREATE?TABLE?`authorities`?(
          ??`username`?varchar(50)?NOT?NULL,
          ??`authority`?varchar(50)?NOT?NULL,
          ??UNIQUE?KEY?`ix_auth_username`?(`username`,`authority`),
          ??CONSTRAINT?`fk_authorities_users`?FOREIGN?KEY?(`username`)?REFERENCES?`users`?(`username`)
          )?ENGINE=InnoDB?DEFAULT?CHARSET=utf8;

          /*Data?for?the?table?`authorities`?*/

          insert??into?`authorities`(`username`,`authority`)?values?('feng','ROLE_vip1');

          /*Table?structure?for?table?`users`?*/

          DROP?TABLE?IF?EXISTS?`users`;

          CREATE?TABLE?`users`?(
          ??`username`?varchar(50)?NOT?NULL,
          ??`password`?varchar(500)?NOT?NULL,
          ??`enabled`?tinyint(1)?NOT?NULL,
          ??PRIMARY?KEY?(`username`)
          )?ENGINE=InnoDB?DEFAULT?CHARSET=utf8;

          /*Data?for?the?table?`users`?*/

          insert??into?`users`(`username`,`password`,`enabled`)?values?('feng','$2a$10$cxCFUH0.O.pWGnp9KhC0He2T9jmQx4AV3mcjWMvmqM6eSq/cHfxFG',1);

          /*!40101?SET?SQL_MODE=@OLD_SQL_MODE?*/;
          /*!40014?SET?FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS?*/;
          /*!40014?SET?UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS?*/;
          /*!40111?SET?SQL_NOTES=@OLD_SQL_NOTES?*/;


          這里插入了一條數(shù)據(jù)肯定會好奇吧,下面在解釋

          在剛才的項目中添加mysql、jdbc依賴


          ????????
          ????????????org.springframework.boot
          ????????????spring-boot-starter-jdbc
          ????????

          ????????
          ????????
          ????????????mysql
          ????????????mysql-connector-java
          ????????????runtime
          ????????


          配置類添加鏈接數(shù)據(jù)庫信息

          application.properties


          spring.thymeleaf.cache=false

          spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
          spring.datasource.url=jdbc:mysql://localhost:3306/testspringsecurity?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
          spring.datasource.username=root
          spring.datasource.password=******


          我們在配置類中注釋掉inMemoryAuthentication的方法

          使用jdbcAuthentication認(rèn)證,改為

          package?com.feng.config;

          import?org.springframework.beans.factory.annotation.Autowired;
          import?org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
          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?javax.sql.DataSource;

          /**
          ?*?

          springsecurity-test


          ?*?


          ?*
          ?*?@author?:?Nicer_feng
          ?*?@date?:?2020-10-13?11:38
          ?**/
          @EnableWebSecurity??//開啟WebSecurity模式
          public?class?SecurityConfig?extends?WebSecurityConfigurerAdapter?{

          ????@Autowired
          ????private?DataSource?dataSource;

          ????@Override
          ????protected?void?configure(AuthenticationManagerBuilder?auth)?throws?Exception?{
          //????????auth.inMemoryAuthentication().passwordEncoder(new?BCryptPasswordEncoder())
          //????????????????.withUser("feng").password(new?BCryptPasswordEncoder().encode("111111"))
          //????????????????.roles("vip1")
          //????????????????.and()
          //????????????????.withUser("user").password(new?BCryptPasswordEncoder().encode("222222"))
          //????????????????.roles("vip2")
          //????????????????.and()
          //????????????????.withUser("admin").password(new?BCryptPasswordEncoder().encode("000000"))
          //????????????????.roles("vip1","vip2","vip3");

          ????????auth.jdbcAuthentication()
          ????????????????.dataSource(dataSource)
          ????????????????.usersByUsernameQuery("select?*?from?users?WHERE?username=?")
          ????????????????.authoritiesByUsernameQuery("select?*?from?authorities?where?username=?")
          ????????????????.passwordEncoder(new?BCryptPasswordEncoder());

          ????}

          ????@Override
          ????protected?void?configure(HttpSecurity?http)?throws?Exception?{
          ????????http.authorizeRequests().antMatchers("/").permitAll()
          ????????????????.antMatchers("/level1/**").hasRole("vip1")
          ????????????????.antMatchers("/level2/**").hasRole("vip2")
          ????????????????.antMatchers("/level3/**").hasRole("vip3");

          ????????http.formLogin().loginPage("/toLogin");

          ????????http.rememberMe().rememberMeParameter("remember");

          ????????http.csrf().disable();

          ????????//開啟自動配置的注銷的功能
          ????????//?/logout?注銷請求
          ????????http.logout().logoutSuccessUrl("/");
          ????}
          }


          重啟服務(wù)器后啟動項目,上面的一串密碼就是123456通過BCrypt加密后符號,因為不加密不能認(rèn)證

          注意數(shù)據(jù)庫的認(rèn)證權(quán)限和用戶密碼信息分開存儲,且用戶權(quán)限前在數(shù)據(jù)庫中要加入**ROLE_**前綴

          123456通過BCrypt加密后為

          $2a$10$1gLSaAn2i4LSiq28ACalg.jOUeTNBWfSJtt19uEySy2vcUsi7qyBy

          啟動后測試(并在數(shù)據(jù)庫中添加賬戶測試登錄)



          版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。

          本文鏈接:

          https://blog.csdn.net/weixin_43876186/article/details/109054037




          粉絲福利:108本java從入門到大神精選電子書領(lǐng)取

          ???

          ?長按上方鋒哥微信二維碼?2 秒
          備注「1234」即可獲取資料以及
          可以進(jìn)入java1234官方微信群



          感謝點贊支持下哈?

          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  噜噜色成人| 中国13一14毛片 | AA片在线播放 | 成人三级视频网站 | 亚洲欧美日韩一级 |