SpringSecurity页面授权与登录验证实现(内存取值与数据库取值)

下面我将详细讲解“SpringSecurity页面授权与登录验证实现(内存取值与数据库取值)”的完整攻略。

一、概述

在开发Web应用程序时,安全性一直是非常重要的一环。Spring Security是Spring Framework所提供的一个强大的安全性框架,能够帮助我们很容易实现认证和授权功能。本文将介绍SpringSecurity页面授权与登录验证实现(内存取值与数据库取值)。

二、SpringSecurity登录验证实现

2.1 内存取值

SpringSecurity提供了一个很强大的内存验证功能,可以通过配置文件进行用户的认证和授权。接下来,我们将学习如何通过SpringSecurity实现基于内存的登录验证。

2.1.1 引入依赖

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-web</artifactId>
  <version>5.4.2</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-config</artifactId>
  <version>5.4.2</version>
</dependency>

2.1.2 配置SpringSecurity

<http use-expressions="true">
  <intercept-url pattern="/login" access="permitAll" />
  <intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')" />
  <form-login login-page="/login" default-target-url="/welcome"
        authentication-failure-url="/login?error" />
  <logout logout-success-url="/login?logout" />
</http>
<authentication-manager>
  <authentication-provider>
    <user-service>
      <user name="admin" password="{noop}admin" authorities="ROLE_ADMIN" />
      <user name="user" password="{noop}user" authorities="ROLE_USER" />
    </user-service>
  </authentication-provider>
</authentication-manager>

这里我们配置了两个用户,admin和user,对应的密码分别是admin和user。同时分配了不同的角色,admin拥有ROLE_ADMIN角色、user拥有ROLE_USER角色。

2.1.3 编写登录页面

<form action="/login" method="post">
  <label for="username">Username:</label>
  <input type="text" id="username" name="username" />
  <br />
  <label for="password">Password:</label>
  <input type="password" id="password" name="password" />
  <br />
  <input type="submit" value="Sign In" />
</form>

2.1.4 编写安全配置类

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
        .anyRequest().authenticated()
        .and()
      .formLogin()
        .loginPage("/login")
        .defaultSuccessUrl("/index")
        .permitAll()
        .and()
      .logout()
        .permitAll();
  }

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
      .inMemoryAuthentication()
        .withUser("admin").password("{noop}admin").roles("ADMIN")
        .and()
        .withUser("user").password("{noop}user").roles("USER");
  }
}

最后,我们启动Web应用程序,并访问http://localhost:8080/login,输入上述两种用户信息分别登录,可以看到根据角色的不同,用户被分配到了不同的页面上。

2.2 数据库取值

与内存取值相比,数据库取值是一种更高级的方法。在这种情况下,我们不再使用配置文件中的用户信息,而是将用户信息存储在数据库中。接下来,我们将学习如何将存储在数据库中的用户信息用于SpringSecurity的登录验证。

2.2.1 引入依赖

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-web</artifactId>
  <version>5.4.2</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-config</artifactId>
  <version>5.4.2</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-data</artifactId>
  <version>5.4.2</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.13</version>
</dependency>
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-dbcp</artifactId>
    <version>${tomcat-dbcp.version}</version>
</dependency>

2.2.2 创建数据库表

我们可以创建一个名为users的表,用于存储用户名、密码和角色信息。SQL语句如下:

CREATE TABLE users(
   username VARCHAR(20),
   password VARCHAR(100),
   enabled TINYINT(1),
   PRIMARY KEY (username)
) ENGINE=InnoDB CHARSET=utf8;

CREATE TABLE authorities (
  username VARCHAR(50) NOT NULL,
  authority VARCHAR(50) NOT NULL,
  CONSTRAINT fk_authorities_users FOREIGN KEY(username) REFERENCES users(username)
)ENGINE=InnoDB CHARSET=utf8;

2.2.3 定义User类

创建一个User类来描述从数据库中检索的用户信息。

public class User implements UserDetails {

  private String username;
  private String password;
  private boolean enabled;

  @Override
  public Collection<? extends GrantedAuthority> getAuthorities() {
    Set<GrantedAuthority> authorities = new HashSet<>();
    // 在这里实现查询用户权限代码,将查询出的权限添加到authorities中
    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 true;
  }

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

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

  // setters 和 getters
}

2.2.4 定义UserDetailsService实现类

在 Spring Security 中,用户详细信息将由 UserDetailsService 负责提供。我们需要定义一个UserDetailsService实现类,用于从数据库中获取用户信息。

@Service
public class MyUserDetailsService implements UserDetailsService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    List<User> userList = jdbcTemplate.query(
      "SELECT * FROM users WHERE username = ?",
      new Object[]{username},
      (rs, rowNum) -> {
        User user = new User();
        user.setUsername(rs.getString("username"));
        user.setPassword(rs.getString("password"));
        user.setEnabled(true);
        return user;
      }
    );
    if (userList.isEmpty()) {
      throw new UsernameNotFoundException("User not found with username: " + username);
    }
    List<GrantedAuthority> authorities = new ArrayList<>();
    jdbcTemplate.query(
        "SELECT * FROM authorities WHERE username = ?",
        new Object[]{username},
        (rs, rowNum) -> {
          authorities.add(new SimpleGrantedAuthority(rs.getString("authority")));
          return null;
        });
    userList.get(0).setAuthorities(authorities);
    return userList.get(0);
  }
}

2.2.5 配置SpringSecurity

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserDetailsService myUserDetailsService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http
          .authorizeRequests()
              .antMatchers("/login", "/login-error").permitAll()
              .antMatchers("/admin/**").hasRole("ADMIN")
              .anyRequest().authenticated()
              .and()
          .formLogin()
              .loginPage("/login")
              .failureUrl("/login-error")
              .defaultSuccessUrl("/index")
              .and()
          .logout()
              .logoutSuccessUrl("/");
    }

    @Bean
    public JdbcUserDetailsManager jdbcUserDetailsManager() throws Exception {
      JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager();
      jdbcUserDetailsManager.setDataSource(dataSource);
      String encodedPassword = passwordEncoder().encode("123456");
      User user = new User("user", encodedPassword, true, Arrays.asList(new SimpleGrantedAuthority("USER")));
      User admin = new User("admin", encodedPassword, true, Arrays.asList(new SimpleGrantedAuthority("USER"), new SimpleGrantedAuthority("ADMIN")));
      jdbcUserDetailsManager.createUser(user);
      jdbcUserDetailsManager.createUser(admin);
      return jdbcUserDetailsManager;
    }
}

2.2.6 编写登录页面

页面与内存取值时的登录页面相同。

2.2.7 配置数据源

# 数据库配置
spring.datasource.url = jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username = root
spring.datasource.password = 123456
spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver

2.2.8 完整示例

我们还可以通过完整的示例代码来加深了解:

https://github.com/delulin/spring-security-jdbc

三、SpringSecurity页面授权实现

3.1 引入依赖

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-web</artifactId>
  <version>5.4.2</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-config</artifactId>
  <version>5.4.2</version>
</dependency>

3.2 页面授权配置

在SpringSecurity中,我们可以通过配置角色来指定哪些用户有权限访问某些资源。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
        .antMatchers("/admin/**").hasRole("ADMIN")
        .antMatchers("/user/**").hasAnyRole("ADMIN", "USER")
        .and()
      .formLogin()
        .loginPage("/login")
        .defaultSuccessUrl("/index")
        .permitAll()
        .and()
      .logout()
        .permitAll();
  }

  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
      .inMemoryAuthentication()
        .withUser("admin").password("{noop}admin").roles("ADMIN")
        .and()
        .withUser("user").password("{noop}user").roles("USER");
  }
}

这里,我们配置了两个角色,ROLE_ADMIN和ROLE_USER。可以看到,通过.antMatchers()方法,我们为/admin/指定了权限为ROLE_ADMIN,为/user/指定了权限为ROLE_ADMIN和ROLE_USER。

3.3 完整示例

我们还可以通过完整的示例代码来加深了解:

https://github.com/delulin/spring-security-demo

四、总结

本文介绍了SpringSecurity如何实现页面授权和登录验证,分别介绍了基于内存和基于数据库的两种实现方法。通过了解SpringSecurity的相关配置和使用方法,我们可以在实际应用当中更好地使用和掌握SpringSecurity,从而保障我们Web应用程序的安全性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringSecurity页面授权与登录验证实现(内存取值与数据库取值) - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • java获取json中的全部键值对实例

    下面是Java获取JSON中的全部键值对的攻略: 步骤一:导入相关包 获取JSON中的全部键值对需要用到Java中的相关包,需要在代码中进行导入,示例代码如下: import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import java.util.Iterator…

    Java 2023年5月26日
    00
  • 利用js制作html table分页示例(js实现分页)

    下面是利用 js 制作 HTML table 分页示例的攻略。 一、分页概述 分页是指将大量的记录拆分成若干个页面进行展示,以减轻页面压力,提高页面加载速度。在实际开发中,我们通常会使用后端语言来实现分页,比如常用的 PHP 分页。但是,为了提高用户体验,我们也可以使用前端语言 JavaScript 来实现分页。 具体的,我们可以使用js将数据分成若干页,然…

    Java 2023年6月16日
    00
  • java基础入门之IO流

    Java基础入门之IO流 本文主要介绍Java IO流的基础知识,包括IO流的概述、IO流分类、IO流的读取和写入操作以及常用IO流示例。 IO流概述 Java IO(Input/Output)流是一种用于处理输入/输出的机制。它提供了一种操作任意数据源的方式,包括磁盘文件、网络连接等等。 Java IO流由四个抽象类组成: InputStream:字节输入…

    Java 2023年5月26日
    00
  • Java的Struts框架报错“ActionServletException”的原因与解决办法

    当使用Java的Struts框架时,可能会遇到“ActionServletException”错误。这个错误通常由以下原因之一起: 配置错误:如果配置文件中存在错误,则可能会出现此。在这种情况下,需要检查配置文件以解决此问题。 类加载错误:如果类加载失败,则可能会出现此。在这种情况下,需要检查类路径以解决此问题。 以下是两个实例: 例 1 如果配置文件中存在…

    Java 2023年5月5日
    00
  • Hibernate的Annotation版Hello world实例

    下面我将为你详细讲解“Hibernate的Annotation版Hello world实例”的完整攻略: 1. 构建项目 首先,我们需要构建一个Maven项目,在项目的pom.xml文件中添加相关依赖: <dependencies> <dependency> <groupId>org.hibernate</group…

    Java 2023年5月20日
    00
  • Java 23种设计模型详解

    Java 23种设计模型详解 Java 23种设计模型是一组在软件开发中广泛使用的可重用的设计思想或解决方案。了解这些设计模型可以帮助软件开发人员更容易地设计和开发高质量的软件系统。本篇攻略详细介绍了Java 23种设计模型,其中包含了每种模型的定义、使用场景、示例程序以及注意事项。 单例模式 定义:确保一个类只有一个实例,并提供该实例的全局访问点。 使用场…

    Java 2023年5月19日
    00
  • springboot整合mybatis实现多表查询的实战记录

    下面就是“springboot整合mybatis实现多表查询的实战记录”的完整攻略。 一、准备工作 1.1 创建一个SpringBoot项目 在IDE中创建一个SpringBoot项目,选择Web、MyBatis、MySQL等依赖。 1.2 导入需要的依赖 在pom.xml文件中导入以下依赖: <!– MyBatis依赖 –> <dep…

    Java 2023年5月20日
    00
  • Hibernate 的原理与配置

    Hibernate是一个面向对象的Java持久化框架,它的目的是简化数据访问,并提供更好的对象封装性和查询性能。本文将讲解Hibernate的原理与配置,包括Hibernate的核心概念、Hibernate工作流程、Hibernate配置文件以及示例代码。 Hibernate的核心概念 Session:Session代表与数据库的一个会话,它包含了一系列的操…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部