国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring Boot開發(fā)Spring Security

這篇具有很好參考價(jià)值的文章主要介紹了Spring Boot開發(fā)Spring Security。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

????????這里我對springboot不做過多描述,因?yàn)槲矣X得學(xué)這個(gè)的肯定掌握了springboot這些基礎(chǔ)

導(dǎo)入核心依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring‐boot‐starter‐security</artifactId>
</dependency>

Servlet Context配置

@Configuration
public class WebConfig implements WebMvcConfigurer {
    //默認(rèn)Url根路徑跳轉(zhuǎn)到/login,此url為spring security提供
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("redirect:/login");
    }
}

Spring Security為我們提供了登錄頁面,這里我是將 "/",路徑設(shè)置為登陸頁面的路徑,方便測試,

也可以自定義登錄頁面,我會在后面說明

application.properties配置文件

server.port=8080
server.servlet.context-path=/security-springboot
spring.application.name = security-springboot

spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp

spring.datasource.url=jdbc:mysql://localhost:3306/user_db
spring.datasource.username=root
spring.datasource.password=XXXX
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

? ? ? ? 至于為什么不是yml,這完全不是這里的重點(diǎn),關(guān)于前端用的jsp,各位看官姥爺們也湊合看吧,理解這個(gè)框架就好,最下面的數(shù)據(jù)庫配置這里也可以先不做,后面也會詳細(xì)說明

核心配置來嘍,WebSecurityConfig

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //定義用戶信息服務(wù)(查詢用戶信息)
/*
    @Bean
    public UserDetailsService userDetailsService(){
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("zhangsan").password("123").authorities("p1").build());
        manager.createUser(User.withUsername("lisi").password("456").authorities("p2").build());
        return manager;
    }
*/

    //密碼編碼器
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //安全攔截機(jī)制(最重要)
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
//                .antMatchers("/r/r1").hasAuthority("p2")
//                .antMatchers("/r/r2").hasAuthority("p2")
                .antMatchers("/r/**").authenticated()//所有/r/**的請求必須認(rèn)證通過
                .anyRequest().permitAll()//除了/r/**,其它的請求可以訪問
                .and()
                .formLogin()//允許表單登錄
                .loginPage("/login-view")//登錄頁面
                .loginProcessingUrl("/login")
                .successForwardUrl("/login-success")//自定義登錄成功的頁面地址
        .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login-view?logout");


    }
}

????????如果不想連接數(shù)據(jù)庫測試,這里可以先把這些注釋解除掉去掉,用模擬數(shù)據(jù)

controller代碼

@RestController
public class LoginController {

    @RequestMapping(value = "/login-success",produces = {"text/plain;charset=UTF-8"})
    public String loginSuccess(){
        //提示具體用戶名稱登錄成功
        return getUsername()+" 登錄成功";
    }

    /**
     * 測試資源1
     * @return
     */
    @GetMapping(value = "/r/r1",produces = {"text/plain;charset=UTF-8"})
    public String r1(){
        return "訪問資源1";
    }

    /**
     * 測試資源2
     * @return
     */
    @GetMapping(value = "/r/r2",produces = {"text/plain;charset=UTF-8"})
    public String r2(){
        return " 訪問資源2";
    }

}

工作原理

Spring Security 所解決的問題就是 安全訪問控制 ,而安全訪問控制功能其實(shí)就是對所有進(jìn)入系統(tǒng)的請求進(jìn)行攔截,
校驗(yàn)每個(gè)請求是否能夠訪問它所期望的資源。根據(jù)前邊知識的學(xué)習(xí),可以通過 Filter AOP 等技術(shù)來實(shí)現(xiàn), Spring
Security Web 資源的保護(hù)是靠 Filter 實(shí)現(xiàn)的,所以從這個(gè) Filter 來入手,逐步深入 Spring Security 原理。
當(dāng)初始化 Spring Security 時(shí),會創(chuàng)建一個(gè)名為 SpringSecurityFilterChain Servlet 過濾器,類型為
org.springframework.security.web.FilterChainProxy ,它實(shí)現(xiàn)了 javax.servlet.Filter ,因此外部的請求會經(jīng)過此
類,下圖是 Spring Security 過慮器鏈結(jié)構(gòu)圖:
Spring Boot開發(fā)Spring Security,spring,spring boot,java
FilterChainProxy 是一個(gè)代理,真正起作用的是 FilterChainProxy SecurityFilterChain 所包含的各個(gè) Filter ,同時(shí)
這些 Filter 作為 Bean Spring 管理,它們是 Spring Security 核心,各有各的職責(zé),但他們并不直接處理用戶的 認(rèn)
,也不直接處理用戶的 授權(quán) ,而是把它們交給了認(rèn)證管理器( AuthenticationManager )和決策管理器
AccessDecisionManager )進(jìn)行處理,下圖是 FilterChainProxy 相關(guān)類的 UML 圖示。
Spring Boot開發(fā)Spring Security,spring,spring boot,java
spring Security 功能的實(shí)現(xiàn)主要是由一系列過濾器鏈相互配合完成。
Spring Boot開發(fā)Spring Security,spring,spring boot,java
下面介紹過濾器鏈中主要的幾個(gè)過濾器及其作用:
SecurityContextPersistenceFilter 這個(gè) Filter 是整個(gè)攔截過程的入口和出口(也就是第一個(gè)和最后一個(gè)攔截
器),會在請求開始時(shí)從配置好的 SecurityContextRepository 中獲取 SecurityContext ,然后把它設(shè)置給
SecurityContextHolder 。在請求完成后將 SecurityContextHolder 持有的 SecurityContext 再保存到配置好
SecurityContextRepository ,同時(shí)清除 securityContextHolder 所持有的 SecurityContext
UsernamePasswordAuthenticationFilter 用于處理來自表單提交的認(rèn)證。該表單必須提供對應(yīng)的用戶名和密
碼,其內(nèi)部還有登錄成功或失敗后進(jìn)行處理的 AuthenticationSuccessHandler
AuthenticationFailureHandler ,這些都可以根據(jù)需求做相關(guān)改變;
FilterSecurityInterceptor 是用于保護(hù) web 資源的,使用 AccessDecisionManager 對當(dāng)前用戶進(jìn)行授權(quán)訪問,前
面已經(jīng)詳細(xì)介紹過了;
ExceptionTranslationFilter 能夠捕獲來自 FilterChain 所有的異常,并進(jìn)行處理。但是它只會處理兩類異常:
AuthenticationException AccessDeniedException ,其它的異常它會繼續(xù)拋出。

認(rèn)證流程

Spring Boot開發(fā)Spring Security,spring,spring boot,java

1. 用戶提交用戶名、密碼被 SecurityFilterChain 中的 UsernamePasswordAuthenticationFilter 過濾器獲取到,
封裝為請求 Authentication ,通常情況下是 UsernamePasswordAuthenticationToken 這個(gè)實(shí)現(xiàn)類。
2. 然后過濾器將 Authentication 提交至認(rèn)證管理器( AuthenticationManager )進(jìn)行認(rèn)證
3. 認(rèn)證成功后, AuthenticationManager 身份管理器返回一個(gè)被填充滿了信息的(包括上面提到的權(quán)限信息,
身份信息,細(xì)節(jié)信息,但密碼通常會被移除) Authentication 實(shí)例。
4. SecurityContextHolder 安全上下文容器將第 3 步填充了信息的 Authentication ,通過
SecurityContextHolder.getContext().setAuthentication(…) 方法,設(shè)置到其中。
可以看出 AuthenticationManager 接口(認(rèn)證管理器)是認(rèn)證相關(guān)的核心接口,也是發(fā)起認(rèn)證的出發(fā)點(diǎn),它
的實(shí)現(xiàn)類為 ProviderManager 。而 Spring Security 支持多種認(rèn)證方式,因此 ProviderManager 維護(hù)著一個(gè)
List<AuthenticationProvider> 列表,存放多種認(rèn)證方式,最終實(shí)際的認(rèn)證工作是由
AuthenticationProvider 完成的。咱們知道 web 表單的對應(yīng)的 AuthenticationProvider 實(shí)現(xiàn)類為
DaoAuthenticationProvider ,它的內(nèi)部又維護(hù)著一個(gè) UserDetailsService 負(fù)責(zé) UserDetails 的獲取。最終
AuthenticationProvider UserDetails 填充至 Authentication
Spring Boot開發(fā)Spring Security,spring,spring boot,java

AuthenticationProvider

通過前面的 Spring Security 認(rèn)證流程 我們得知,認(rèn)證管理器( AuthenticationManager )委托
AuthenticationProvider 完成認(rèn)證工作。
AuthenticationProvider 是一個(gè)接口,定義如下:
public interface AuthenticationProvider {
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
    boolean supports(Class<?> var1);
}
authenticate () 方法定義了 認(rèn)證的實(shí)現(xiàn)過程 ,它的參數(shù)是一個(gè) Authentication ,里面包含了登錄用戶所提交的用
戶、密碼等。而返回值也是一個(gè) Authentication ,這個(gè) Authentication 則是在認(rèn)證成功后,將用戶的權(quán)限及其他信
息重新組裝后生成。
Spring Security 中維護(hù)著一個(gè) List<AuthenticationProvider> 列表,存放多種認(rèn)證方式,不同的認(rèn)證方式使用不
同的 AuthenticationProvider 。如使用用戶名密碼登錄時(shí),使用 AuthenticationProvider1 ,短信登錄時(shí)使用
AuthenticationProvider2 等等這樣的例子很多。
每個(gè) AuthenticationProvider 需要實(shí)現(xiàn) supports () 方法來表明自己支持的認(rèn)證方式,如我們使用表單方式認(rèn)證,
在提交請求時(shí) Spring Security 會生成 UsernamePasswordAuthenticationToken ,它是一個(gè) Authentication ,里面
封裝著用戶提交的用戶名、密碼信息。而對應(yīng)的,哪個(gè) AuthenticationProvider 來處理它?
我們在 DaoAuthenticationProvider 的基類 AbstractUserDetailsAuthenticationProvider 發(fā)現(xiàn)以下代碼:
public boolean supports(Class<?> authentication) {
    return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
也就是說當(dāng) web 表單提交用戶名密碼時(shí), Spring Security DaoAuthenticationProvider 處理。
最后,我們來看一下 Authentication ( 認(rèn)證信息 ) 的結(jié)構(gòu),它是一個(gè)接口,我們之前提到的
UsernamePasswordAuthenticationToken 就是它的實(shí)現(xiàn)之一:
public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    Object getCredentials();
    Object getDetails();
    Object getPrincipal();
    boolean isAuthenticated();
    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}
1 Authentication spring security 包中的接口,直接繼承自 Principal 類,而 Principal 是位于 java.security
包中的。它是表示著一個(gè)抽象主體身份,任何主體都有一個(gè)名稱,因此包含一個(gè) getName() 方法。
2 getAuthorities() ,權(quán)限信息列表,默認(rèn)是 GrantedAuthority 接口的一些實(shí)現(xiàn)類,通常是代表權(quán)限信息的一系
列字符串。
3 getCredentials() ,憑證信息,用戶輸入的密碼字符串,在認(rèn)證過后通常會被移除,用于保障安全。
4 getDetails() ,細(xì)節(jié)信息, web 應(yīng)用中的實(shí)現(xiàn)接口通常為 WebAuthenticationDetails ,它記錄了訪問者的 ip 地 址和sessionId 的值。
5 getPrincipal() ,身份信息,大部分情況下返回的是 UserDetails 接口的實(shí)現(xiàn)類, UserDetails 代表用戶的詳細(xì)
信息,那從 Authentication 中取出來的 UserDetails 就是當(dāng)前登錄用戶信息,它也是框架中的常用接口之一。

UserDetailsService

現(xiàn)在咱們現(xiàn)在知道 DaoAuthenticationProvider 處理了 web 表單的認(rèn)證邏輯,認(rèn)證成功后既得到一個(gè)
Authentication(UsernamePasswordAuthenticationToken 實(shí)現(xiàn) ) ,里面包含了身份信息( Principal )。這個(gè)身份 信息就是一個(gè) Object ,大多數(shù)情況下它可以被強(qiáng)轉(zhuǎn)為 UserDetails 對象。
DaoAuthenticationProvider 中包含了一個(gè) UserDetailsService 實(shí)例,它負(fù)責(zé)根據(jù)用戶名提取用戶信息
UserDetails( 包含密碼 ) ,而后 DaoAuthenticationProvider 會去對比 UserDetailsService 提取的用戶密碼與用戶提交
的密碼是否匹配作為認(rèn)證成功的關(guān)鍵依據(jù),因此可以通過將自定義的 UserDetailsService 公開為 spring bean 來定 義自定義身份驗(yàn)證。
很多人把 DaoAuthenticationProvider UserDetailsService 的職責(zé)搞混淆,其實(shí) UserDetailsService 只負(fù)責(zé)從特定 的地方(通常是數(shù)據(jù)庫)加載用戶信息,僅此而已。而DaoAuthenticationProvider 的職責(zé)更大,它完成完整的認(rèn) 證流程,同時(shí)會把UserDetails 填充至 Authentication 。
上面一直提到 UserDetails 是用戶信息,咱們看一下它的真面目:
public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    String getPassword();
    String getUsername();
    boolean isAccountNonExpired();
    boolean isAccountNonLocked();
    boolean isCredentialsNonExpired();
    boolean isEnabled();
}
它和 Authentication 接口很類似,比如它們都擁有 username authorities 。 Authentication getCredentials() 與 UserDetails中的 getPassword() 需要被區(qū)分對待,前者是用戶提交的密碼憑證,后者是用戶實(shí)際存儲的密碼,認(rèn)證 其實(shí)就是對這兩者的比對。Authentication 中的 getAuthorities() 實(shí)際是由 UserDetails getAuthorities() 傳遞而形 成的。還記得Authentication 接口中的 getDetails() 方法嗎?其中的 UserDetails 用戶詳細(xì)信息便是經(jīng)過了 AuthenticationProvider認(rèn)證之后被填充的。
通過實(shí)現(xiàn) UserDetailsService UserDetails ,我們可以完成對用戶信息獲取方式以及用戶信息字段的擴(kuò)展。
Spring Security 提供的 InMemoryUserDetailsManager( 內(nèi)存認(rèn)證 ) , JdbcUserDetailsManager(jdbc 認(rèn)證 ) 就是 UserDetailsService的實(shí)現(xiàn)類,主要區(qū)別無非就是從內(nèi)存還是從數(shù)據(jù)庫加載用戶

PasswordEncoder

DaoAuthenticationProvider 認(rèn)證處理器通過 UserDetailsService 獲取到 UserDetails 后,它是如何與請求 Authentication中的密碼做對比呢?
在這里 Spring Security 為了適應(yīng)多種多樣的加密類型,又做了抽象, DaoAuthenticationProvider 通過 PasswordEncoder接口的 matches 方法進(jìn)行密碼的對比,而具體的密碼對比細(xì)節(jié)取決于實(shí)現(xiàn)
public interface PasswordEncoder {
    String encode(CharSequence var1);
    boolean matches(CharSequence var1, String var2);
    default boolean upgradeEncoding(String encodedPassword) {
    return false;
    }
}
Spring Security 提供很多內(nèi)置的 PasswordEncoder ,能夠開箱即用,使用某種 PasswordEncoder 只需要進(jìn)行如
下聲明即可,如下:
@Bean
public PasswordEncoder passwordEncoder() {
    return NoOpPasswordEncoder.getInstance();
}
NoOpPasswordEncoder 采用字符串匹配方法,不對密碼進(jìn)行加密比較處理,密碼比較流程如下:
1 、用戶輸入密碼(明文 )
2 、 DaoAuthenticationProvider 獲取 UserDetails (其中存儲了用戶的正確密碼)
3 DaoAuthenticationProvider 使用 PasswordEncoder 對輸入的密碼和正確的密碼進(jìn)行校驗(yàn),密碼一致則校驗(yàn)通
過,否則校驗(yàn)失敗。
NoOpPasswordEncoder 的校驗(yàn)規(guī)則拿 輸入的密碼和 UserDetails 中的正確密碼進(jìn)行字符串比較,字符串內(nèi)容一致
則校驗(yàn)通過,否則 校驗(yàn)失敗。
實(shí)際項(xiàng)目中推薦使用 BCryptPasswordEncoder, Pbkdf2PasswordEncoder, SCryptPasswordEncoder 等,感興趣
的大家可以看看這些 PasswordEncoder 的具體實(shí)現(xiàn)。

授權(quán)流程

通過 快速上手 我們知道, Spring Security 可以通過 http.authorizeRequests() web 請求進(jìn)行授權(quán)保護(hù)。 Spring
Security 使用標(biāo)準(zhǔn) Filter 建立了對 web 請求的攔截,最終實(shí)現(xiàn)對資源的授權(quán)訪問。

Spring Boot開發(fā)Spring Security,spring,spring boot,java

1. 攔截請求 ,已認(rèn)證用戶訪問受保護(hù)的 web 資源將被 SecurityFilterChain 中的 FilterSecurityInterceptor 的子
類攔截。
2. 獲取資源訪問策略 FilterSecurityInterceptor 會從 SecurityMetadataSource 的子類
DefaultFilterInvocationSecurityMetadataSource 獲取要訪問當(dāng)前資源所需要的權(quán)限
Collection<ConfigAttribute> 。
SecurityMetadataSource 其實(shí)就是讀取訪問策略的抽象,而讀取的內(nèi)容,其實(shí)就是我們配置的訪問規(guī)則, 讀
取訪問策略如:

Spring Boot開發(fā)Spring Security,spring,spring boot,java

(不過后面我們都會從數(shù)據(jù)庫中拿)

3. 最后, FilterSecurityInterceptor 會調(diào)用 AccessDecisionManager 進(jìn)行授權(quán)決策,若決策通過,則允許訪問資
源,否則將禁止訪問

授權(quán)決策

AccessDecisionManager 采用 投票 的方式來確定是否能夠訪問受保護(hù)資源。

Spring Boot開發(fā)Spring Security,spring,spring boot,java

AffirmativeBased 的邏輯是:
1 )只要有 AccessDecisionVoter 的投票為 ACCESS_GRANTED 則同意用戶進(jìn)行訪問;
2 )如果全部棄權(quán)也表示通過;
3 )如果沒有一個(gè)人投贊成票,但是有人投反對票,則將拋出 AccessDeniedException
Spring security 默認(rèn)使用的是 AffirmativeBased 。
ConsensusBased 的邏輯是:
1 )如果贊成票多于反對票則表示通過。
2 )反過來,如果反對票多于贊成票則將拋出 AccessDeniedException 。
3 )如果贊成票與反對票相同且不等于 0 ,并且屬性 allowIfEqualGrantedDeniedDecisions 的值為 true ,則表 示通過,否則將拋出異常AccessDeniedException 。參數(shù) allowIfEqualGrantedDeniedDecisions 的值默認(rèn)為 true
4 )如果所有的 AccessDecisionVoter 都棄權(quán)了,則將視參數(shù) allowIfAllAbstainDecisions 的值而定,如果該值
true 則表示通過,否則將拋出異常 AccessDeniedException 。參數(shù) allowIfAllAbstainDecisions 的值默認(rèn)為 false
UnanimousBased 的邏輯與另外兩種實(shí)現(xiàn)有點(diǎn)不一樣,另外兩種會一次性把受保護(hù)對象的配置屬性全部傳遞
AccessDecisionVoter 進(jìn)行投票,而 UnanimousBased 會一次只傳遞一個(gè) ConfigAttribute
AccessDecisionVoter 進(jìn)行投票。這也就意味著如果我們的 AccessDecisionVoter 的邏輯是只要傳遞進(jìn)來的
ConfigAttribute 中有一個(gè)能夠匹配則投贊成票,但是放到 UnanimousBased 中其投票結(jié)果就不一定是贊成了。
UnanimousBased 的邏輯具體來說是這樣的:
1 )如果受保護(hù)對象配置的某一個(gè) ConfigAttribute 被任意的 AccessDecisionVoter 反對了,則將拋出
AccessDeniedException 。
2 )如果沒有反對票,但是有贊成票,則表示通過。
3 )如果全部棄權(quán)了,則將視參數(shù) allowIfAllAbstainDecisions 的值而定, true 則通過, false 則拋出
AccessDeniedException

自定義認(rèn)證

自定義登錄頁面

快速上手 中,你可能會想知道登錄頁面從哪里來的?因?yàn)槲覀儾]有提供任何的 HTML JSP 文件。 Spring
Security 的默認(rèn)配置沒有明確設(shè)定一個(gè)登錄頁面的 URL ,因此 Spring Security 會根據(jù)啟用的功能自動生成一個(gè)登錄
頁面 URL ,并使用默認(rèn) URL 處理登錄的提交內(nèi)容,登錄后跳轉(zhuǎn)的到默認(rèn) URL 等等。盡管自動生成的登錄頁面很方便
快速啟動和運(yùn)行,但大多數(shù)應(yīng)用程序都希望定義自己的登錄頁面。

Spring Boot開發(fā)Spring Security,spring,spring boot,java

@Configuration//就相當(dāng)于springmvc.xml文件
public class WebConfig implements WebMvcConfigurer {


    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("redirect:/login-view");
        registry.addViewController("/login-view").setViewName("login");

    }

}
//配置安全攔截機(jī)制
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/r/**").authenticated()
.anyRequest().permitAll()
.and()
.formLogin() (1)
.loginPage("/login‐view") (2)
.loginProcessingUrl("/login") (3)
.successForwardUrl("/login‐success") (4)
.permitAll();
}
1 )允許表單登錄
2 )指定我們自己的登錄頁 ,spring security 以重定向方式跳轉(zhuǎn)到 /login-view
3 )指定登錄處理的 URL ,也就是用戶名、密碼表單提交的目的路徑
4 )指定登錄成功后的跳轉(zhuǎn) URL
5 )我們必須允許所有用戶訪問我們的登錄頁(例如為驗(yàn)證的用戶),這個(gè) formLogin().permitAll() 方法允許
任意用戶訪問基于表單登錄的所有的 URL 。

問題解決

spring security 為防止 CSRF Cross-site request forgery 跨站請求偽造)的發(fā)生,限制了除了 get 以外的大多數(shù)方法。
解決方法 1
屏蔽 CSRF 控制,即 spring security 不再限制 CSRF 。
配置 WebSecurityConfig
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable() //屏蔽CSRF控制,即spring security不再限制CSRF
    ...
}

連接數(shù)據(jù)庫認(rèn)證

????????創(chuàng)建數(shù)據(jù)庫

CREATE DATABASE `user_db` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE TABLE `t_user` (
    `id` bigint(20) NOT NULL COMMENT '用戶id',
    `username` varchar(64) NOT NULL,
    `password` varchar(64) NOT NULL,
    `fullname` varchar(255) NOT NULL COMMENT '用戶姓名',
    `mobile` varchar(11) DEFAULT NULL COMMENT '手機(jī)號',
    PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC

application.properties配置

spring.datasource.url=jdbc:mysql://localhost:3306/user_db
spring.datasource.username=root
spring.datasource.password=mysql
spring.datasource.driver‐class‐name=com.mysql.jdbc.Driver
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring‐boot‐starter‐jdbc</artifactId>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql‐connector‐java</artifactId>
    <version>5.1.47</version>
</dependency>

pom.xml添加依賴,mysql版本根據(jù)自己情況文章來源地址http://www.zghlxwxcb.cn/news/detail-822457.html

定義模型類型,在model包定義UserDto

@Data
public class UserDto {
    private String id;
    private String username;
    private String password;
    private String fullname;
    private String mobile;
}

Dao包定義UserDao

@Repository
public class UserDao {
@Autowired
JdbcTemplate jdbcTemplate;
public UserDto getUserByUsername(String username){
String sql ="select id,username,password,fullname from t_user where username = ?";
List<UserDto> list = jdbcTemplate.query(sql, new Object[]{username}, new
BeanPropertyRowMapper<>(UserDto.class));
if(list == null && list.size() <= 0){
return null;
}
return list.get(0);
}
}

定義UserDetailService

@Service
public class SpringDataUserDetailsService implements UserDetailsService {
@Autowired
UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//登錄賬號
System.out.println("username="+username);
//根據(jù)賬號去數(shù)據(jù)庫查詢...
UserDto user = userDao.getUserByUsername(username);
if(user == null){
return null;
}
//這里暫時(shí)使用靜態(tài)數(shù)據(jù)
UserDetails userDetails =
User.withUsername(user.getFullname()).password(user.getPassword()).authorities("p1").build();
return userDetails;
}
}

使用BCryptPasswordEncoder

WebSecurityConfig中
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}
UserDetails 中的密碼存儲 BCrypt 格式
前邊實(shí)現(xiàn)了從數(shù)據(jù)庫查詢用戶信息,所以數(shù)據(jù)庫中的密碼應(yīng)該存儲 BCrypt 格式
Spring Boot開發(fā)Spring Security,spring,spring boot,java

會話

獲取用戶身份

編寫 LoginController ,實(shí)現(xiàn) /r/r1 、 /r/r2 的測試資源,并修改 loginSuccess 方法,注意 getUsername 方法, Spring
Security 獲取當(dāng)前登錄用戶信息的方法為 SecurityContextHolder.getContext().getAuthentication()
@RestController
public class LoginController {

    @RequestMapping(value = "/login-success",produces = {"text/plain;charset=UTF-8"})
    public String loginSuccess(){
        //提示具體用戶名稱登錄成功
        return getUsername()+" 登錄成功";
    }

    /**
     * 測試資源1
     * @return
     */
    @GetMapping(value = "/r/r1",produces = {"text/plain;charset=UTF-8"})
    public String r1(){
        return getUsername()+" 訪問資源1";
    }

    /**
     * 測試資源2
     * @return
     */
    @GetMapping(value = "/r/r2",produces = {"text/plain;charset=UTF-8"})
    public String r2(){
        return getUsername()+" 訪問資源2";
    }

    //獲取當(dāng)前用戶信息
    private String getUsername(){
        String username = null;
        //當(dāng)前認(rèn)證通過的用戶身份
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //用戶身份
        Object principal = authentication.getPrincipal();
        if(principal == null){
            username = "匿名";
        }
        if(principal instanceof org.springframework.security.core.userdetails.UserDetails){
            UserDetails userDetails = (UserDetails) principal;
            username = userDetails.getUsername();
        }else{
            username = principal.toString();
        }
        return username;
    }
}

會話控制

Spring Boot開發(fā)Spring Security,spring,spring boot,java
通過以下配置方式對該選項(xiàng)進(jìn)行配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement()
    .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}
默認(rèn)情況下, Spring Security 會為每個(gè)登錄成功的用戶會新建一個(gè) Session ,就是 ifRequired 。
若選用 never ,則指示 Spring Security 對登錄成功的用戶不創(chuàng)建 Session 了,但若你的應(yīng)用程序在某地方新建了
session ,那么 Spring Security 會用它的。
若使用 stateless ,則說明 Spring Security 對登錄成功的用戶不會創(chuàng)建 Session 了,你的應(yīng)用程序也不會允許新建
session 。并且它會暗示不使用 cookie ,所以每個(gè)請求都需要重新進(jìn)行身份驗(yàn)證。這種無狀態(tài)架構(gòu)適用于 REST API
及其無狀態(tài)認(rèn)證機(jī)制。

會話超時(shí)

spring boot 配置文件
server.servlet.session.timeout = 3600s
session 超時(shí)之后,可以通過 Spring Security 設(shè)置跳轉(zhuǎn)的路徑
http.sessionManagement()
    .expiredUrl("/login‐view?error=EXPIRED_SESSION")
    .invalidSessionUrl("/login‐view?error=INVALID_SESSION");
expired session 過期, invalidSession 指傳入的 sessionid 無效

安全會話cookie

我們可以使用 httpOnly secure 標(biāo)簽來保護(hù)我們的會話 cookie
httpOnly :如果為 true ,那么瀏覽器腳本將無法訪問 cookie
secure :如果為 true ,則 cookie 將僅通過 HTTPS 連接發(fā)送
spring boot 配置文件:
server.servlet.session.cookie.http‐only = true
server.servlet.session.cookie.secure = true

退出

Spring security 默認(rèn)實(shí)現(xiàn)了 logout 退出,訪問 /logout ,果然不出所料,退出功能 Spring 也替我們做好了。
點(diǎn)擊 “Log Out” 退出 成功。
退出 后訪問其它 url 判斷是否成功退出。
這里也可以自定義退出成功的頁面
.and()
    .logout()
    .logoutUrl("/logout")
    .logoutSuccessUrl("/login‐view?logout");
當(dāng)退出操作出發(fā)時(shí),將發(fā)生:
????????使HTTP Session 無效
????????清除 SecurityContextHolder
????????跳轉(zhuǎn)到 /login - view?logout
但是,類似于配置登錄功能,咱們可以進(jìn)一步自定義退出功能:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
//...
.and()
.logout() (1)
.logoutUrl("/logout") (2)
.logoutSuccessUrl("/login‐view?logout") (3)
.logoutSuccessHandler(logoutSuccessHandler) (4)
.addLogoutHandler(logoutHandler) (5)
.invalidateHttpSession(true); (6)
}
1 )提供系統(tǒng)退出支持,使用 WebSecurityConfigurerAdapter 會自動被應(yīng)用
2 )設(shè)置觸發(fā)退出操作的 URL ( 默認(rèn)是 /logout ).
3 )退出之后跳轉(zhuǎn)的 URL 。默認(rèn)是 /login?logout 。
4 )定制的 LogoutSuccessHandler ,用于實(shí)現(xiàn)用戶退出成功時(shí)的處理。如果指定了這個(gè)選項(xiàng)那么
logoutSuccessUrl() 的設(shè)置會被忽略。
5 )添加一個(gè) LogoutHandler ,用于實(shí)現(xiàn)用戶退出時(shí)的清理工作 . 默認(rèn) SecurityContextLogoutHandler 會被添加
為最后一個(gè) LogoutHandler
6 )指定是否在退出時(shí)讓 HttpSession 無效。 默認(rèn)設(shè)置為 true 。
注意:如果讓 logout GET 請求下生效,必須關(guān)閉防止 CSRF 攻擊 csrf().disable() 。如果開啟了 CSRF ,必須使用
post 方式請求 /logout
logoutHandler
一般來說, LogoutHandler 的實(shí)現(xiàn)類被用來執(zhí)行必要的清理,因而他們不應(yīng)該拋出異常。
下面是 Spring Security 提供的一些實(shí)現(xiàn):
PersistentTokenBasedRememberMeServices 基于持久化 token RememberMe 功能的相關(guān)清理
TokenBasedRememberMeService 基于 token RememberMe 功能的相關(guān)清理
CookieClearingLogoutHandler 退出時(shí) Cookie 的相關(guān)清理
CsrfLogoutHandler 負(fù)責(zé)在退出時(shí)移除 csrfToken
SecurityContextLogoutHandler 退出時(shí) SecurityContext 的相關(guān)清理
鏈?zhǔn)?/span> API 提供了調(diào)用相應(yīng)的 LogoutHandler 實(shí)現(xiàn)的快捷方式,比如 deleteCookies() 。

到了這里,關(guān)于Spring Boot開發(fā)Spring Security的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Spring Boot 如何使用 Spring Security 進(jìn)行認(rèn)證和授權(quán)

    Spring Boot 如何使用 Spring Security 進(jìn)行認(rèn)證和授權(quán)

    在 Web 應(yīng)用程序中,認(rèn)證和授權(quán)是非常重要的功能。Spring Security 是一個(gè)基于 Spring 框架的強(qiáng)大的安全框架,它提供了完整的認(rèn)證和授權(quán)解決方案,并且可以輕松地集成到 Spring Boot 應(yīng)用程序中。本文將介紹如何在 Spring Boot 中使用 Spring Security 進(jìn)行認(rèn)證和授權(quán),并提供示例代碼。

    2024年02月11日
    瀏覽(37)
  • Spring boot 3 (3.1.5) Spring Security 設(shè)置一

    項(xiàng)目依賴中添加: 創(chuàng)建Security設(shè)置文件: SecutiryConfig.java 測試 創(chuàng)建兩個(gè)路由 /api/welcome 和 /api/admin。分別訪問。 /api/welcome 直接就能看到內(nèi)容, /api/admin 則返回401 附錄: JsonResult代碼 JWTFilter.java代碼見下期,還沒整明白。 -完-

    2024年02月06日
    瀏覽(14)
  • Spring Boot安全管理—Spring Security基本配置

    Spring Boot安全管理—Spring Security基本配置

    1.1 創(chuàng)建項(xiàng)目,添加依賴 創(chuàng)建一個(gè)Spring Boot Web 項(xiàng)目,然后添加spring-boot-starter-security依賴。 1.2 添加hello接口 在項(xiàng)目中添加一個(gè)簡單的/hello接口,內(nèi)容如下: 1.3 啟動項(xiàng)目測試 訪問/hello接口會自動跳轉(zhuǎn)到登錄頁面,這個(gè)頁面有Spring Security提供的。 默認(rèn)的用戶名是user,默認(rèn)的登

    2024年02月08日
    瀏覽(21)
  • spring boot security使用jwt認(rèn)證

    spring boot security使用jwt認(rèn)證

    在前面的幾篇文章中: spring boot security快速使用示例 spring boot security之前后端分離配置 spring boot security自定義認(rèn)證 spring boot security驗(yàn)證碼登錄示例 基本對常用的基于cookie和session的認(rèn)證使用場景都已覆蓋。但是session屬于有狀態(tài)認(rèn)證,本文給出一個(gè)無狀態(tài)的認(rèn)證:jwt認(rèn)證示例。

    2024年02月12日
    瀏覽(17)
  • spring boot security驗(yàn)證碼登錄示例

    spring boot security驗(yàn)證碼登錄示例

    在spring boot security自定義認(rèn)證一文,基本給出了一個(gè)完整的自定義的用戶登錄認(rèn)證的示例,但是未涉及到驗(yàn)證的使用,本文介紹登錄的時(shí)候如何使用驗(yàn)證碼。 本文介紹一個(gè)驗(yàn)證碼生成工具,比較老的一個(gè)庫了,僅作demo使用,不太建議生產(chǎn)用了,因?yàn)槿绻愕拇a需要進(jìn)行安全

    2024年02月12日
    瀏覽(14)
  • Java Spring Boot 開發(fā)框架

    Spring Boot是一種基于Java編程語言的開發(fā)框架,它的目標(biāo)是簡化Java應(yīng)用程序的開發(fā)過程。Spring Boot提供了一種快速、易于使用的方式來創(chuàng)建獨(dú)立的、生產(chǎn)級別的Java應(yīng)用程序。本文將介紹Spring Boot的特性、優(yōu)勢以及如何使用它來開發(fā)高效、可靠的應(yīng)用程序。 Spring Boot是由Pivotal團(tuán)隊(duì)

    2024年02月08日
    瀏覽(24)
  • Spring Boot 3.1中如何整合Spring Security和Keycloak

    Spring Boot 3.1中如何整合Spring Security和Keycloak

    在今年2月14日的時(shí)候,Keycloak 團(tuán)隊(duì)宣布他們正在棄用大多數(shù) Keycloak 適配器。其中包括Spring Security和Spring Boot的適配器,這意味著今后Keycloak團(tuán)隊(duì)將不再提供針對Spring Security和Spring Boot的集成方案。但是,如此強(qiáng)大的Keycloak,還要用怎么辦呢?本文就來聊聊,在最新的Spring Boot

    2024年02月07日
    瀏覽(24)
  • 【Spring Boot Admin】使用(整合Spring Security服務(wù),添加鑒權(quán))

    【Spring Boot Admin】使用(整合Spring Security服務(wù),添加鑒權(quán))

    Spring Boot Admin 監(jiān)控平臺 背景:Spring Boot Admin 監(jiān)控平臺不添加鑒權(quán)就直接訪問的話,是非常不安全的。所以在生產(chǎn)環(huán)境中使用時(shí),需要添加鑒權(quán),只有通過鑒權(quán)后才能監(jiān)控客戶端服務(wù)。本文整合Spring Security進(jìn)行實(shí)現(xiàn)。 pom依賴 yml配置 啟動類@EnableAdminServer 安全配置類:SecuritySe

    2024年02月16日
    瀏覽(45)
  • Spring Boot Security認(rèn)證:Redis緩存用戶信息

    Spring Boot Security認(rèn)證:Redis緩存用戶信息

    ??歡迎來到架構(gòu)設(shè)計(jì)專欄~Spring Boot Security認(rèn)證:Redis緩存用戶信息 ☆* o(≧▽≦)o *☆嗨~我是IT·陳寒?? ?博客主頁:IT·陳寒的博客 ??該系列文章專欄:架構(gòu)設(shè)計(jì) ??其他專欄:Java學(xué)習(xí)路線 Java面試技巧 Java實(shí)戰(zhàn)項(xiàng)目 AIGC人工智能 數(shù)據(jù)結(jié)構(gòu)學(xué)習(xí) ??文章作者技術(shù)和水平有限,如

    2024年02月04日
    瀏覽(21)
  • 【8】Spring Boot 3 集成組件:安全組件 spring security【官網(wǎng)概念篇】

    【8】Spring Boot 3 集成組件:安全組件 spring security【官網(wǎng)概念篇】

    個(gè)人主頁: 【??個(gè)人主頁】 需要您的【?? 點(diǎn)贊+關(guān)注】支持 ?? ?? 本文核心知識點(diǎn): spring security B 官網(wǎng)Doc : Spring Security Spring Security 是一個(gè)框架,它提供 身份驗(yàn)證 、 授權(quán) 和針對常見 攻擊的保護(hù) 。它具有保護(hù)命令式和響應(yīng)式應(yīng)用程序的一流支持,是保護(hù)基于spring的應(yīng)用

    2024年02月03日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包