91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot安全管理之基于數據庫認證的方法

發布時間:2022-08-13 10:01:31 來源:億速云 閱讀:329 作者:iii 欄目:開發技術

這篇“SpringBoot安全管理之基于數據庫認證的方法”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“SpringBoot安全管理之基于數據庫認證的方法”文章吧。

1. 設計數據表

用戶表、角色表、用戶角色關聯表

SpringBoot安全管理之基于數據庫認證的方法

建表語句

CREATE TABLE `role` (
  `id` int(11) NOT NULL,
  `name` varchar(32) DEFAULT NULL,
  `nameZh` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user` (
  `id` int(11) NOT NULL,
  `username` varchar(32) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `enabled` varchar(1) DEFAULT NULL,
  `locked` varchar(1) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user_role` (
  `id` int(11) NOT NULL,
  `uid` int(11) DEFAULT NULL,
  `rid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

初始化數據

注意:角色名有一個默認的前綴 ROLE_

INSERT INTO `user`(`id`, `username`, `password`, `enabled`, `locked`) VALUES (1, 'root', '$2a$10$x6CBW1qnQqKPIxUSefZN7ebfTEiYNnfzzVjPJzlRhg5XyMzSWoO4e', '1', '0');
INSERT INTO `user`(`id`, `username`, `password`, `enabled`, `locked`) VALUES (2, 'admin', '$2a$10$x6CBW1qnQqKPIxUSefZN7ebfTEiYNnfzzVjPJzlRhg5XyMzSWoO4e', '1', '0');
INSERT INTO `user`(`id`, `username`, `password`, `enabled`, `locked`) VALUES (3, 'tangsan', '$2a$10$x6CBW1qnQqKPIxUSefZN7ebfTEiYNnfzzVjPJzlRhg5XyMzSWoO4e', '1', '0');
INSERT INTO `role`(`id`, `name`, `nameZh`) VALUES (1, 'ROLE_dba', '數據庫管理員');
INSERT INTO `role`(`id`, `name`, `nameZh`) VALUES (2, 'ROLE_admin', '系統管理員');
INSERT INTO `role`(`id`, `name`, `nameZh`) VALUES (3, 'ROLE_user', '普通用戶');
INSERT INTO `user_role`(`id`, `uid`, `rid`) VALUES (1, 1, 1);
INSERT INTO `user_role`(`id`, `uid`, `rid`) VALUES (2, 1, 2);
INSERT INTO `user_role`(`id`, `uid`, `rid`) VALUES (3, 2, 2);
INSERT INTO `user_role`(`id`, `uid`, `rid`) VALUES (4, 3, 3);

2. 創建項目

MyBatis 靈活,JPA 便利,此處選擇前者,創建 Spring Boot Web 項目添加如下依賴:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>1.3.2</version>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.1.10</version>
</dependency>

3. 配置數據庫

在 application.properties 中進行數據連接配置

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/jpa

4. 創建實體類

Role

public class Role {
    private Integer id;
    private String name;
    private String nameZh;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getNameZh() {
        return nameZh;
    }
    public void setNameZh(String nameZh) {
        this.nameZh = nameZh;
    }
}

User

public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
    private List<Role> roles;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }
    @Override
    public String getPassword() {
        return password;
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return !locked;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
   public Boolean getEnabled() {
       return enabled;
    }
    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }
    public Boolean getLocked() {
        return locked;
    }
    public void setLocked(Boolean locked) {
        this.locked = locked;
    }
    public List<Role> getRoles() {
        return roles;
    }
    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }
}

代碼解釋:

用戶實體類需要實現 UserDetails 接口,并且實現該接口中的 7 個方法

| 方法名 | 解釋 |

| &mdash; | &mdash; |

| getAuthorities() | 獲取當前用戶對象所具有的角色信息 |

| getPassword() | 獲取當前用戶對象的密碼 |

| getUsername() | 獲取當前用戶對象的用戶名 |

| isAccountNonExpired() | 當前賬號是否未過期 |

| isAccountNonLocked() | 當前賬號是否未鎖定 |

| isCredentialsNonExpired() | 當前賬號密碼是否未過期 |

| isEnabled() | 當前賬號是否可用 |

用戶根據實際情況設置這 7 個方法的返回值。因為默認情況下不需要開發者自己進行密碼角色等信息的比對,開發者只需要提供相關信息即可,例如 getPassword() 方法返回的密碼和用戶輸入的密碼不匹配,會自動拋出 BadCredentialsException 異常,isAccountNonExpired() 方法返回了 false ,會自動拋出 AccountExpiredException 異常,因此對開發者而言,只需要按照數據庫中的數據在這里返回相應的配置即可。此處因為數據庫中只有 enabled 和 locked 字段,故帳號未過期和密碼未過期兩個方法都返回 true

getAuthorities() 用來獲取當前用戶所具有的角色信息,此處用戶所具有的角色存儲在 roles 屬性中,因此該方法直接遍歷 roles 屬性,然后構造 SimpleGrantedAuthority 集合并返回

5. 創建UserService

@Service
public class UserService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.loadUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("賬戶不存在!");
        }
        user.setRoles(userMapper.getUserRolesByUid(user.getId()));
        return user;
    }
}

代碼解釋:

  • 定義 UserService 實現 UserDetailsService 接口,并實現該接口中的 loadUserByUsername 方法,該方法的參數就是用戶登錄時輸入的用戶名,通過用戶名去數據庫中查找用戶,如果沒有查詢到用戶,就拋出一個賬號不存在的異常,如果查找到了用戶,就繼續查詢該用戶所具有的角色信息,并將獲取到的 user 對象返回,再由系統提供的 DaoAuthenticationProvider 類去比對密碼是否正確

  • loadUserByUsername 方法將在用戶登錄時自動調用

涉及到的 UserMapper 和 UserMapper.xml 如下

@Mapper
public interface UserMapper {
    User loadUserByUsername(String username);
    List<Role> getUserRolesByUid(Integer id);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.sang.mapper.UserMapper">
    <select id="loadUserByUsername" resultType="org.sang.model.User">
        select * from user where username=#{username}
    </select>
    <select id="getUserRolesByUid" resultType="org.sang.model.Role">
        select * from role r,user_role ur where r.id=ur.rid and ur.uid=#{id}
    </select>
</mapper>

6. 配置Spring Security

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/db/**").hasRole("dba")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/login").permitAll()
                .and()
                .csrf().disable();
    }
}

此處的配置與上篇介紹的一致,唯一不同的是沒有配置內存用戶,而是將剛剛創建好的 UserService 配置到 AuthenticationManagerBuilder 中。

7.創建Controller

@RestController
public class HelloController {
    @GetMapping("/admin/hello")
    public String admin() {
        return "hello admin";
    }
    @GetMapping("/db/hello")
    public String dba() {
        return "hello dba";
    }
    @GetMapping("/user/hello")
    public String user() {
        return "hello user";
    }
}

8. 測試

登錄 admin 用戶,訪問 /admin/hello,報了以下錯誤

Invalid bound statement (not found)

pom.xml 新增以下配置

<build>
  <resources>
    <resource>
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.xml</include>
      </includes>
    </resource>
    <resource>
      <directory>src/main/resources</directory>
    </resource>
  </resources>
</build>

再次登錄訪問 /admin/hello,報了以下錯誤

Caused by: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: Illegal overloaded getter method with ambiguous type for property enabled in class class org.sang.model.User. This breaks the JavaBeans specification and can cause unpredictable results.

去掉 User 實體類中 enabled 屬性的 get set 方法,如下

public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
    private List<Role> roles;
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }
    @Override
    public String getPassword() {
        return password;
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return !locked;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Boolean getLocked() {
        return locked;
    }
    public void setLocked(Boolean locked) {
        this.locked = locked;
    }
    public List<Role> getRoles() {
        return roles;
    }
    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }
}

再次登錄訪問 /admin/hello

SpringBoot安全管理之基于數據庫認證的方法

訪問 /db/hello

SpringBoot安全管理之基于數據庫認證的方法

訪問 /user/hello

SpringBoot安全管理之基于數據庫認證的方法

以上就是關于“SpringBoot安全管理之基于數據庫認證的方法”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宜春市| 陈巴尔虎旗| 灵宝市| 九寨沟县| 凤山市| 佛冈县| 永定县| 龙海市| 温泉县| 城口县| 中山市| 莫力| 金堂县| 鱼台县| 扬州市| 永和县| 伊通| 玉环县| 久治县| 恩施市| 新巴尔虎右旗| 吉安县| 西平县| 宜君县| 汕头市| 平凉市| 青阳县| 东安县| 普宁市| 余干县| 鄂尔多斯市| 遵义县| 芦溪县| 山东省| 洛南县| 黑水县| 常德市| 定结县| 扶余县| 田林县| 南城县|