成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【SpringSecurity系列01】初識SpringSecurity

elva / 2692人閱讀

摘要:什么是是一個能夠?yàn)榛诘钠髽I(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。它來自于,那么它與整合開發(fā)有著天然的優(yōu)勢,目前與對應(yīng)的開源框架還有。通常大家在做一個后臺管理的系統(tǒng)的時候,應(yīng)該采用判斷用戶是否登錄。

? 什么是SpringSecurity ?

?      Spring Security是一個能夠?yàn)榛赟pring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。它提供了一組可以在Spring應(yīng)用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉(zhuǎn)Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面編程)功能,為應(yīng)用系統(tǒng)提供聲明式的安全訪問控制功能,減少了為企業(yè)系統(tǒng)安全控制編寫大量重復(fù)代碼的工作。

以上來介紹來自wiki,比較官方。

? 用自己的話 簡單介紹一下,Spring Security 基于 Servlet 過濾器鏈的形式,為我們的web項(xiàng)目提供認(rèn)證授權(quán)服務(wù)。它來自于Spring,那么它與SpringBoot整合開發(fā)有著天然的優(yōu)勢,目前與SpringSecurity對應(yīng)的開源框架還有shiro。接下來我將通過一個簡單的例子帶大家來認(rèn)識SpringSecurity,然后通過分析它的源碼帶大家來認(rèn)識一下SpringSecurity是如何工作,從一個簡單例子入門,大家由淺入深的了解學(xué)習(xí)SpringSecurity。

通常大家在做一個后臺管理的系統(tǒng)的時候,應(yīng)該采用session判斷用戶是否登錄。我記得我在沒有接觸學(xué)習(xí)SpringSecurity與shiro之前。對于用戶登錄功能實(shí)現(xiàn)通常是如下:

public String login(User user, HttpSession session){
  //1、根據(jù)用戶名或者id從數(shù)據(jù)庫讀取數(shù)據(jù)庫中用戶
  //2、判斷密碼是否一致
      //3、如果密碼一致
          session.setAttribute("user",user);
      //4、否則返回登錄頁面
  
}

對于之后那些需要登錄之后才能訪問的url,通過SpringMvc的攔截器中的#preHandle來判斷session中是否有user對象
如果沒有 則返回登錄頁面
如果有, 則允許訪問這個頁面。

但是在SpringSecurity中,這一些邏輯已經(jīng)被封裝起來,我們只需要簡單的配置一下就能使用。

接下來我通過一個簡單例子大家認(rèn)識一下SpringSecurity

本文基于SpringBoot,如果大家對SpringBoot不熟悉的話可以看看我之前寫的SpringBoot入門系列

我使用的是:

SpringBoot 2.1.4.RELEASE

SpringSecurity 5



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.4.RELEASE
         
    
    com.yukong
    springboot-springsecurity
    0.0.1-SNAPSHOT
    springboot-springsecurity
    springboot-springsecurity study

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-security
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            2.0.1
        
        
            mysql
            mysql-connector-java
            runtime
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.springframework.security
            spring-security-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


配置一下數(shù)據(jù)庫 以及MyBatis

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncoding=utf8
    password: abc123
mybatis:
  mapper-locations: classpath:mapper/*.xml

這里我用的MySQL8.0 大家注意一下 MySQL8.0的數(shù)據(jù)庫驅(qū)動的類的包改名了

在前面我有講過SpringBoot中如何整合Mybatis,在這里我就不累述,有需要的話看這篇文章

user.sql

CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT "主鍵",
  `username` varchar(32) NOT NULL COMMENT "用戶名",
  `svc_num` varchar(32) DEFAULT NULL COMMENT "用戶號碼",
  `password` varchar(100) DEFAULT NULL COMMENT "密碼",
  `cust_id` bigint(20) DEFAULT NULL COMMENT "客戶id  1對1",
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

對應(yīng)的UserMapper.java

package com.yukong.mapper;

import com.yukong.entity.User;

/**
 *
 * @author yukong
 * @date 2019-04-11 16:50
 */
public interface UserMapper {

    int insertSelective(User record);

    User selectByUsername(String  username);


}

UserMapper.xml




  
    
    
    
    
    
  
  
    id, username, svc_num, `password`, cust_id
  
  

  
    insert into user
    
      
        username,
      
      
        svc_num,
      
      
        `password`,
      
      
        cust_id,
      
    
    
      
        #{username,jdbcType=VARCHAR},
      
      
        #{svcNum,jdbcType=VARCHAR},
      
      
        #{password,jdbcType=VARCHAR},
      
      
        #{custId,jdbcType=BIGINT},
      
    
  

在這里我們定義了兩個方法。

國際慣例ctrl+shift+t創(chuàng)建mapper的測試方法,并且插入一條記錄

package com.yukong.mapper;

import com.yukong.SpringbootSpringsecurityApplicationTests;
import com.yukong.entity.User;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;

import static org.junit.Assert.*;

/**
 * @author yukong
 * @date 2019-04-11 16:53
 */

public class UserMapperTest extends SpringbootSpringsecurityApplicationTests {


    @Autowired
    private UserMapper userMapper;


    @Test
    public void insert() {
        User user = new User();
        user.setUsername("yukong");
        user.setPassword("abc123");
        userMapper.insertSelective(user);
    }

}

運(yùn)行測試方法,并且成功插入一條記錄。

創(chuàng)建UserController.java

package com.yukong.controller;

import com.yukong.entity.User;
import com.yukong.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author yukong
 * @date 2019-04-11 15:22
 */
@RestController
public class UserController {
    
    @Autowired
    private UserMapper userMapper;

    @RequestMapping("/user/{username}")
    public User hello(@PathVariable String username) {
        return userMapper.selectByUsername(username);
    }

}

這個方法就是根據(jù)用戶名去數(shù)據(jù)庫查找用戶詳細(xì)信息。

啟動。因?yàn)槲覀冎安迦脒^一條username=yukong的記錄,所以我們查詢一下,訪問127.0.0.1:8080/user/yukong

[圖片上傳失敗...(image-ea02ac-1554981869345)]

我們可以看到 我們被重定向到了一個登錄界面,這也是我們之前引入的spring-boot-security-starter起作用了。

大家可能想問了,用戶名跟密碼是什么,用戶名默認(rèn)是user,密碼在啟動的時候已經(jīng)通過日志打印在控制臺了。

現(xiàn)在我們輸入用戶跟密碼并且登錄。就可以成功訪問我們想要訪問的接口。

從這里我們可以知道,我只需要引入了Spring-Security的依賴,它就開始生效,并且保護(hù)我們的接口了,但是現(xiàn)在有一個問題就是,它的用戶名只能是user并且密碼是通過日志打印在控制臺,但是我們希望它能通過數(shù)據(jù)來訪問我們的用戶并且判斷登錄。

其實(shí)想實(shí)現(xiàn)這個功能也很簡單。這里我們需要了解兩個接口。

UserDetails

UserDetailsService

所以,我們需要將我們的User.java實(shí)現(xiàn)這個接口

package com.yukong.entity;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

/**
 *
 * @author yukong
 * @date 2019-04-11 16:50
 */
public class User implements UserDetails {
    /**
    * 主鍵
    */
    private Long id;

    /**
    * 用戶名
    */
    private String username;

    /**
    * 用戶號碼
    */
    private String svcNum;

    /**
    * 密碼
    */
    private String password;

    /**
    * 客戶id  1對1
    */
    private Long custId;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return false;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getSvcNum() {
        return svcNum;
    }

    public void setSvcNum(String svcNum) {
        this.svcNum = svcNum;
    }

    @Override
    public Collection getAuthorities() {
        // 這里我們沒有用到權(quán)限,所以返回一個默認(rèn)的admin權(quán)限
        return AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
    }

    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Long getCustId() {
        return custId;
    }

    public void setCustId(Long custId) {
        this.custId = custId;
    }
}

接下來我們再看看UserDetailsService

它只有一個方法的聲明,就是通過用戶名去查找用戶信息,從這里我們應(yīng)該知道了,SpringSecurity回調(diào)UserDetails#loadUserByUsername去獲取用戶,但是它不知道用戶信息存在哪里,所以定義成接口,讓使用者去實(shí)現(xiàn)。在我們這個項(xiàng)目用 我們的用戶是存在了數(shù)據(jù)庫中,所以我們需要調(diào)用UserMapper的方法去訪問數(shù)據(jù)庫查詢用戶信息。這里我們新建一個類叫MyUserDetailsServiceImpl

package com.yukong.config;

import com.yukong.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
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.Service;

/**
 * @author yukong
 * @date 2019-04-11 17:35
 */
@Service
public class MyUserDetailServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userMapper.selectByUsername(username);
    }
}

然后新建一個類去把我們的UserDetailsService配置進(jìn)去

這里我們新建一個SecurityConfig

package com.yukong.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @author yukong
 * @date 2019-04-11 15:08
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;


    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // 配置UserDetailsService 跟 PasswordEncoder 加密器
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
        auth.eraseCredentials(false);
    }
}

在這里我們還配置了一個PasswordEncoder加密我們的密碼,大家都知道密碼明文存數(shù)據(jù)庫是很不安全的。

接下里我們插入一條記錄,需要注意的是 密碼需要加密。

package com.yukong.mapper;

import com.yukong.SpringbootSpringsecurityApplicationTests;
import com.yukong.entity.User;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;

import static org.junit.Assert.*;

/**
 * @author yukong
 * @date 2019-04-11 16:53
 */

public class UserMapperTest extends SpringbootSpringsecurityApplicationTests {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserMapper userMapper;


    @Test
    public void insert() {
        User user = new User();
        user.setUsername("yukong");
        user.setPassword(passwordEncoder.encode("abc123"));
        userMapper.insertSelective(user);
    }

}

接下來啟動程序,并且登錄,這次只需要輸入插入到數(shù)據(jù)中的那條記錄的用戶名跟密碼即可。

在這里一節(jié)中,我們了解到如何使用springsecurity 完成一個登錄功能,接下我們將通過分析源碼來了解為什么需要這個配置,以及SpringSecurity的工作原理是什么。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/77554.html

相關(guān)文章

  • 兩年了,我寫了這些干貨!

    摘要:開公眾號差不多兩年了,有不少原創(chuàng)教程,當(dāng)原創(chuàng)越來越多時,大家搜索起來就很不方便,因此做了一個索引幫助大家快速找到需要的文章系列處理登錄請求前后端分離一使用完美處理權(quán)限問題前后端分離二使用完美處理權(quán)限問題前后端分離三中密碼加鹽與中異常統(tǒng)一處理 開公眾號差不多兩年了,有不少原創(chuàng)教程,當(dāng)原創(chuàng)越來越多時,大家搜索起來就很不方便,因此做了一個索引幫助大家快速找到需要的文章! Spring Boo...

    huayeluoliuhen 評論0 收藏0
  • SpringSecurity01(springSecurity執(zhí)行流程02)

    摘要:里面配置的過濾器鏈當(dāng)用戶使用表單請求時進(jìn)入返回一個的實(shí)例一般是從數(shù)據(jù)庫中查詢出來的實(shí)例然后直接到最后一個如果有錯則拋錯給前面一個進(jìn)行拋錯如果沒有錯則放行可以訪問對應(yīng)的資源上面是總的執(zhí)行流程下面單獨(dú)說一下的認(rèn)證流程這個圖應(yīng)該都看得懂和里面的配 showImg(https://segmentfault.com/img/bVbvO0O?w=1258&h=261);web.xml里面配置的過濾...

    Dr_Noooo 評論0 收藏0
  • SpringSecurity01(使用傳統(tǒng)的xml方式開發(fā),且不連接數(shù)據(jù)庫)

    摘要:創(chuàng)建一個工程在里面添加依賴,依賴不要隨便改我改了出錯了好幾次都找不到原因可以輕松的將對象轉(zhuǎn)換成對象和文檔同樣也可以將轉(zhuǎn)換成對象和配置 1.創(chuàng)建一個web工程2.在pom里面添加依賴,依賴不要隨便改,我改了出錯了好幾次都找不到原因 UTF-8 1.7 1.7 2.5.0 1.2 3.0-alpha-1 ...

    Gilbertat 評論0 收藏0
  • SpringSecurity系列02】SpringSecurity 表單認(rèn)證邏輯源碼解讀

    摘要:通過上面我們知道對于表單登錄的認(rèn)證請求是交給了處理的,那么具體的認(rèn)證流程如下從上圖可知,繼承于抽象類。中維護(hù)這一個對象列表,通過遍歷判斷并且最后選擇對象來完成最后的認(rèn)證。發(fā)布一個登錄事件。 概要 前面一節(jié),通過簡單配置即可實(shí)現(xiàn)SpringSecurity表單認(rèn)證功能,而今天這一節(jié)將通過閱讀源碼的形式來學(xué)習(xí)SpringSecurity是如何實(shí)現(xiàn)這些功能, 前方高能預(yù)警,本篇分析源碼篇幅較...

    zzir 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<