Spring Security 四種添加用戶的方式


官網: https://spring.io/projects/spring-security
https://spring.io/guides/topicals/spring-security-architecture/
https://spring.io/guides/gs/securing-web/
參考書籍:springboot實戰(我的書是基於4.X的,例子有些舊,已經不適用)

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
認證與訪問控制框架
Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements
爲應用提供認證與授權服務

簡單的說就是spring security 可以提供一個登陸功能,只有通過驗證的用戶才能訪問(認證)。並且可以設置不同權限的人訪問不同的頁面(授權)。

(一)簡單的默認配置

搭建了一個空的springboot工程,簡單的controller和hello.html
在這裏插入圖片描述
.pom引入

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

在這裏插入圖片描述
啓動的時候控制檯會打印默認的密碼
在這裏插入圖片描述
訪問http://localhost:8081/liviaSecurity/hello 會自動跳轉到http://localhost:8081/liviaSecurity/login
使用user和密碼可以登錄了

當然我們並不想要用他默認的登錄頁面用戶信息也要自己定。

(二)創建用戶

Spring Security provides some configuration helpers to quickly get common authentication manager features set up in your application. The most commonly used helper is the AuthenticationManagerBuilder which is great for setting up in-memory, JDBC or LDAP user details, or for adding a custom UserDetailsService.

添加用戶一共有四種方式 in-memory, JDBC or LDAP,UserDetailsService
在這裏插入圖片描述

(1)inMemoryAuthentication 用戶放在內存中

首先我們要新建一個配置文件WebSecurityConfig 繼承WebSecurityConfigurerAdapter,重寫configure (AuthenticationManagerBuilder auth)方法。

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure (AuthenticationManagerBuilder auth) throws Exception{
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("yourName")
                .password(new BCryptPasswordEncoder().encode("abc"))
                .roles("ADMIN")
                .and()
                .withUser("user")
                .password(new BCryptPasswordEncoder().encode("abc"))
                .roles("USER");
    }
}

這樣就可以用yourName/abc來登錄系統
注意:

  • java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id “null”
    security5.X 需要添加 PasswordEncoder 否則會報錯
  • ROLE_ADMIN cannot start with ROLE_ (it is automatically added)
    roles("ADMIN ") 是用來爲用戶添加權限的默認**ROLE_**前綴不需要寫成ROLE_ADMIN

如果有spring-boot-autoconfigure包,不用加註解@EnableWebSecurity,如下圖
在這裏插入圖片描述

The WebSecurityConfig class is annotated with @EnableWebSecurity to enable Spring Security’s web security support and provide the Spring MVC integration. It also extends WebSecurityConfigurerAdapter and overrides a couple of its methods to set some specifics of the web security configuration.

如果是springMVC工程的話需要加@EnableWebSecurity
參考:https://blog.csdn.net/andy_zhang2007/article/details/90023901

(2)jdbcAuthentication 用戶放在數據庫中

在這裏插入圖片描述

(2.1)如果使用security默認的表結構

如上圖位置,我的mysql貌似版本太低調整了一下建表語句如下圖創建表 users 和authorities

CREATE TABLE users(username VARCHAR(50) NOT NULL PRIMARY KEY,PASSWORD VARCHAR(500) NOT NULL,enabled BOOLEAN NOT NULL);
CREATE TABLE authorities (username VARCHAR(50) NOT NULL,authority VARCHAR(50) NOT NULL,CONSTRAINT fk_authorities_users FOREIGN KEY(username) REFERENCES users(username));
CREATE UNIQUE INDEX ix_auth_username ON authorities (username,authority);

新增用戶和權限 密碼是abc在BCryptPasswordEncoder加密後的值

INSERT users  VALUES('yourName','$2a$10$6Ed5ZXTH9DNwKzeFU07Ks.jGr3beIjU3o6mi12Jgh4Rh2t0goLbqO',1);
INSERT users  VALUES('user','$2a$10$6Ed5ZXTH9DNwKzeFU07Ks.jGr3beIjU3o6mi12Jgh4Rh2t0goLbqO',1);
INSERT authorities VALUES('yourName','ADMIN');
INSERT authorities VALUES('user','USER');

yml配置數據源,pom添加jar包
在這裏插入圖片描述
pom 我平時用的是jpa,這裏使用jdbc

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<version>8.0.18</version>
</dependency>
    @Qualifier("dataSource")
    @Autowired
    private  DataSource datasource;

    @Override
    protected void configure (AuthenticationManagerBuilder auth) throws Exception{
        auth.jdbcAuthentication().dataSource(datasource);
    }

在這裏插入圖片描述
查詢邏輯如上圖所示,參考:
https://blog.csdn.net/wangmx1993328/article/details/81834974
https://blog.csdn.net/qq_41754409/article/details/101115900

(2.2)使用自己的表結構

但是一般情況下我們的用戶表要用自定義的
假設表結構如下

CREATE TABLE `users1` (
  `username1` VARCHAR(50) NOT NULL,
  `password1` VARCHAR(500) NOT NULL,
  `enabled1` TINYINT(1) NOT NULL,
  `otherColumn` VARCHAR(500) NOT NULL,
  PRIMARY KEY (`username1`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;


CREATE TABLE `authorities1` (
  `username1` VARCHAR(50) NOT NULL,
  `authority1` VARCHAR(50) NOT NULL,
  `otherColumn` VARCHAR(500) NOT NULL,
  UNIQUE KEY `ix_auth_username` (`username1`,`authority1`),
  CONSTRAINT `fk_authorities_users1` FOREIGN KEY (`username1`) REFERENCES `users1` (`username1`)
) ENGINE=INNODB DEFAULT CHARSET=utf8

所以要重寫查詢的sql語句

@Configuration
@Slf4j
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Qualifier("dataSource")
    @Autowired
    private  DataSource datasource;

    @Override
    protected void configure (AuthenticationManagerBuilder auth) throws Exception{
        auth.jdbcAuthentication().dataSource(datasource)
                .authoritiesByUsernameQuery("select username1,authority1 from authorities1 where username1 = ? ")
                .usersByUsernameQuery("select username1,password1,enabled1 from users1 where username1 = ?");
    }
}

(3)ldapAuthentication

對ldap不是很瞭解,有需要的可以參考 https://www.cnblogs.com/youcong/p/9386186.html
https://stackoverflow.com/questions/21555280/how-to-use-spring-ldap-authentication
https://www.it1352.com/967139.html

(4)userDetailsService 自定義

實現UserDetailsService 接口 通過用戶名查詢用戶信息,可以從數據庫裏查,也可以寫在內存中。
我這裏放了一個固定的用戶,在之後可以用springcontextholder獲取

public class CustomUserService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        if(!"yourName".equals(userName)){
            return new UserInfo();
        }
        return new UserInfo(userName);
    }
}
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Bean
    UserDetailsService customUserService(){
        return new CustomUserService();
    }

    @Override
    protected void configure (AuthenticationManagerBuilder auth) throws Exception{
        auth.userDetailsService(customUserService()).passwordEncoder(passwordEncoder());
    }

}

自定義一個用戶信息,

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class UserInfo implements UserDetails {

    private String username;

    private String password;

    private String info;

    UserInfo(){

    }

    UserInfo(String userName){
        this.setUsername(userName);
        this.setPassword(new BCryptPasswordEncoder().encode("abc"));
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }
    /**
     * 賬戶是否過期
     * @return
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    /**
     * 是否禁用
     * @return
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    /**
     * 密碼是否過期
     * @return
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    /**
     * 是否啓用
     * @return
     */
    @Override
    public boolean isEnabled() {
        return true;
    }
}

參考:
https://blog.csdn.net/linhaibing009/article/details/85147801
https://www.bookstack.cn/read/spring-security-tutorial/docs-jpa-userdetailsservice.md

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章