SpringBoot+SpringSecurity集成權限管理快速打造企業級聲明式安全認證授權解決方案之SpringBoot+SpringSecurity+mybatis+mysql

1 主要目的

SpringBoot+SpringSecurity集成權限管理快速打造企業級聲明式安全認證授權解決方案之SpringBoot+SpringSecurity+mybatis+mysql

2 spring boot介紹

2.1 spring boot是什麼?
Spring Boot 是由 Pivotal 團隊提供的全新框架,其設計目的是用來簡化Spring應用的初始搭建以及開發過程。
Spring Boot可以輕鬆創建獨立的,生產級的基於Spring的應用程序。
2.2 spring boot解決了哪些問題?
 spring boot 使編碼變的更簡單
 spring boot 使配置變的更簡單
 spring boot 使部署變的更簡單
 。。。。

2.2.1 使編碼變的簡單
在這裏插入圖片描述

2.2.2 使得配置變的簡單
在這裏插入圖片描述

2.2.3 使得部署變的簡單
在這裏插入圖片描述

3 Spring Boot入門

3.1 Spring boot環境搭建
環境說明:Idea + maven+jdk1.8+mysql

搭建步驟:
一:瀏覽器輸入:start.spring.io
在這裏插入圖片描述

二:拷貝生成的項目,並使用Idea打開即可

在這裏插入圖片描述

3.2 Hello World
第一個:創建Controller

@Controller
public class HelloWorldController {

    @RequestMapping("/hello")
    @ResponseBody
    public String showHelloWolrd(){
        return "hello word";
    }
}

第二個:運行main方法

第三個:瀏覽器輸入地址:http://localhost:8080/hello
在這裏插入圖片描述

項目結構如下:
在這裏插入圖片描述

總結:
1.創建一個maven工程,然後添加依賴即可(添加parent ,添加相關的啓動器,例如:添加web)
2.創建一個引導類(SpringBootAplication.class)
3.創建Controller即可。

4 Spring Boot的屬性配置

4.1 application.properties
默認的情況下,springboot 所有的屬性配置都在application.properties中進行配置,我們可以在裏面添加必要的屬性及對應的值,比如:默認的情況下 啓動項目,使用端口8080,可以設置端口爲其他。例如:
在這裏插入圖片描述

訪問時即可 使用8081.

其他的屬性配置,參考如下文檔:
https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

4.2 自定義屬性值及獲取
有時需要自定義配置屬性文件,設置值,並在代碼中使用它,可以在application.properties中設置。

例如:
 定義值:
在這裏插入圖片描述
 獲取值:

直接通過@value註解獲取即可。
在這裏插入圖片描述

4.3 java config獲取屬性值
由於如果屬性值比較多,一個一個通過@value註解的方式來獲取,比較繁瑣,可以通過java類進行映射,將屬性值映射到java類中,並交給spring管理,使用時直接注入即可,比較方便。

例如:

第一個:定義屬性:
在這裏插入圖片描述

第二個:定義映射屬性的類: 並設置getter和setter方法
在這裏插入圖片描述

@ConfigurationProperties(prefix = "mail")
@Component
public class MailPropertiesConfig {
    private String host;
    private String username;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getUsername() {
        return username;
    }

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

第三個:使用屬性文件中的值:直接注入即可。
在這裏插入圖片描述

5 mybatis的集成

在正式的項目中,需要將數據從數據庫中查詢出來展示到前臺相關的業務邏輯中。所有持久層的技術必不可少,這裏我們介紹現階段比較流行的持久層框架mybatis集成到springboot中。

5.1 mybatis集成的環境搭建
第一個:添加mybatis、mysql的依賴座標:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.1</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

第二個:創建數據庫實例,並配置連接信息
在這裏插入圖片描述

創建數據庫實例,並導入如上圖所示的sql。

spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/sbc
spring.datasource.username=root
spring.datasource.password=itcast

第三個:創建mapper(dao)接口

public interface UserMapper {

    @Select(value = "select * from user where username=#{username}")
    public User selectByUsername(String username);
}

第四個:掃描mapper接口所在的包,將由spring創建這些接口的代理對象
在這裏插入圖片描述

第五:測試,在test目錄下實現測試

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootApplicationTests {

   @Autowired
   private UserMapper mapper;
   @Test
   public void contextLoads() {
      System.out.println(mapper.selectByUsername("zhangsan"));
   }

}

測試OK

集成mybatis 總結:
1.添加mybaits的啓動器的依賴,
2.添加mysql的依賴
3.配置連接池的信息(application.properties配置連接數據庫的用戶名和密碼以及數據庫驅動,URL)
4.編寫mapper接口(相當於是Dao)
5.測試

5.2 頁面展示用戶相關信息
5.2.1 編寫service 接口及實現類

public interface UserService {
    public User selectUserByUsername(String username);
}
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public User selectUserByUsername(String username) {
        return userMapper.selectByUsername(username);
    }
}

結構如下圖:

在這裏插入圖片描述

5.2.2 編寫controller

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/user/info")
    @ResponseBody
    public User info(){
        return userService.selectUserByUsername("zhangsan");
    }
}

其他的CURD與此類似,此處不再討論。

6 spring security介紹

隨着互聯網的發展,當我們在淘寶或者京東上很方便的購物時,是否會想到我們的這種便利,如果不能保證我們的賬號安全的話,可想而知會出現什麼樣的後果。所以,系統的安全性顯得尤爲重要。當用戶購買下訂單時,系統必須要驗證此用戶的身份和相應的權限。而如果使用springmvc的攔截器,驗證過程顯得非常繁瑣。利用spring boot 和spring security將大大簡化我們的配置項和提高網站的安全性。
Spring Security是一個基於spring專注於爲Java應用程序提供身份驗證(Authentication)和授權(Authorization)的框架。同時在 Web 請求級和方法調用級處理身份確認和授權。

7 spring security入門

springsecurity 使用4.2.4.RELEASE版本。

第一個:添加依賴:

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

第二個:測試,訪問之前寫好的hello world
啓動項目 並在瀏覽器中輸入:http://localhost:8081/user/info
如圖:
在這裏插入圖片描述

默認的情況下:spring boot 和spring security已經集成 並攔截所有的請求,需要驗證通過才能放行。彈出框的方式 是默認的spring security的認證方式即(http basic的方式)

默認的情況下:用戶名爲user 密碼爲每次啓動項目是所生成的的隨機字符串,如圖:

在這裏插入圖片描述

8 表單登錄認證

正常的情況下,目前的驗證的方式不是我們想要的,更多的時候,需要有一個表單的登錄界面來進行用戶的身份確認(認證)。所以此時不能滿足我們的需要,我們修改成表單的方式來登錄。

第一個:創建配置類繼承WebSecurityConfigurerAdapter,進行配置。

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().authenticated()//授權所有的請求 都需要通過認證才能訪問
                .and()//並且
                .formLogin();//採用表單提交的方式進行認證登錄
    }
}

第二個:啓動項目,測試;輸入地址:http://localhost:8081/user/info

輸入用戶名和密碼即可。
在這裏插入圖片描述

9 自定義用戶認證

認證包括三個方面:第一個 獲取用戶的信息,第二個 校驗用戶 第三個 密碼加密

用戶的信息獲取主要使用mybatis獲取用戶信息,將獲取到的用戶的信息和頁面傳遞過來的用戶的信息進行匹配,如果成功,則放行,如果失敗,則返回錯誤的信息。匹配的過程是由spring security自己本身來實現的。

用戶的信息獲取需要通過實現一個接口:UserDetailsService 來實現這個功能。

@Component
public class MyUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //從數據庫中獲取到用戶的信息
        return new User(username,"123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

此時任何的用戶只要輸入了密碼爲123即可登錄成功。
因此需要從數據庫中查詢數據,並校驗數據的密碼是否正確

@Component
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //從數據庫中獲取到用戶的信息
        com.itheima.springboot.pojo.User user = userService.selectUserByUsername(username);
        if(user==null){
            return null;//表示不存在
        }
        
        return new User(username,user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

此時如果還有其他的需求,比如:當用戶名和密碼都正確但是有時這個用戶已經被凍結了,此時也不能登錄成功,如果要實現這個需求,那麼需要對UserDetails接口說明一下。代碼需要重新構造:

@Component
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //從數據庫中獲取到用戶的信息
        com.itheima.springboot.pojo.User user = userService.selectUserByUsername(username);
        if(user==null){
            return null;//表示不存在
        }

        //校驗用戶是否已經被凍結  用戶已經被凍結
        boolean flagNonlock = false;//已經被凍結

//        return new User(username,user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
        return new User(username,user.getPassword(),true,true,true,flagNonlock, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

此時,用戶查詢的數據的數據是明文的,在企業開發中,密碼需要加密進行處理,不能以明文展示。此時需要加密。在spring security 中,處理加密的是一個passwordEncoder接口。

只需配置一個passwordEncoder接口的實現類即可。

首先配置passwordEncoder:

@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

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

    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().authenticated()//授權所有的請求 都需要通過認證才能訪問
                .and()//並且
                .formLogin();//採用表單提交的方式進行認證登錄

    }
}

修改校驗邏輯:

@Component
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //從數據庫中獲取到用戶的信息
        com.itheima.springboot.pojo.User user = userService.selectUserByUsername(username);
        if(user==null){
            return null;//表示不存在
        }
        //進行加密;注意此處不應該這麼寫,此處的方法應當在用戶註冊的時候調用此方法進行加密處理,驗證身份時直接獲取數據庫中加過密的信息即可。
        String encode = passwordEncoder.encode(user.getPassword());
        System.out.println("密碼》》》"+encode);

        //校驗用戶是否已經被凍結  用戶已經被凍結
//        boolean flagNonlock = true;
      return new User(username,encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
//        return new User(username,encode,true,true,true,flagNonlock, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

自定義用戶認證
總結:
1.獲取用戶的信息的校驗(UserDetailsService)
2.處理用戶的校驗的業務邏輯處理(UserDetails)
3.密碼的加密(PasswordEncoder)—BCryptPasswordEncoder

10 源碼地址

https://github.com/YouAreOnlyOne/SpringBootSecurity

發佈了48 篇原創文章 · 獲贊 32 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章