SpringBoot整合SpringSecurity

SpringBoot整合SpringSecurity

xml 复制代码
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
     <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--
    对SpringBoot应用的监控
 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

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

<!--
    SpringBoot框架的启动器
-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>

<!--
    SpringBoot框架的测试库
 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

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

sql

sql 复制代码
CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL
);

Users.java

java 复制代码
package com.sin.pojo;

/**
 * @createTime 2023/10/26 9:02
 * @createAuthor SIN
 * @use
 */

public class Users {
    private Integer id;
    private String username;
    private String password;

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

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

UsersMapper.java

java 复制代码
package com.sin.mapper;

import com.sin.pojo.Users;
import org.apache.ibatis.annotations.Mapper;

/**
 * @createTime 2023/10/26 9:03
 * @createAuthor SIN
 * @use
 */
@Mapper
public interface UsersMapper {

    /**
     * 添加数据
     * @param user 
     */
    void insertUser(Users user);

    /**
     * 根据username查询数据
     * @param username
     * @return
     */
    Users findByUsername(String username);
}

UsersMapper.xml

xml 复制代码
<?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="com.sin.mapper.UsersMapper">
      <!-- 添加数据 -->
    <insert id="insertUser" parameterType="com.sin.pojo.Users">
        INSERT INTO users (username, password) VALUES (#{username}, #{password})
    </insert>
    
	<!-- 查询数据 -->
    <select id="findByUsername" parameterType="String" resultType="com.sin.pojo.Users">
        SELECT * FROM users WHERE username = #{username}
    </select>

</mapper>

UsersService.java

java 复制代码
package com.sin.service;

import com.sin.pojo.Users;

/**
 * @createTime 2023/10/26 9:05
 * @createAuthor SIN
 * @use
 */
public interface UsersService {

    /**
     * 用户注册注册
     * @param user
     */
    void registerUser(Users user);

    /**
     * 用户登录
     * @param username
     * @param password
     * @return
     */
    boolean loginUser(String username, String password);
}

UsersServiceImpl.java

java 复制代码
package com.sin.service.impl;

import com.sin.mapper.UsersMapper;
import com.sin.pojo.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @createTime 2023/10/26 9:06
 * @createAuthor SIN
 * @use
 */
@Service
public class UsersServiceImpl implements com.sin.service.UsersService {
    @Autowired
    private UsersMapper usersMapper;

    /**
     * 注册
     * @param users
     */
    @Override
    public void registerUser(Users users) {
        usersMapper.insertUser(users);
    }

    /**
     * 登录
     * @param username
     * @param password
     * @return
     */
    @Override
    public boolean loginUser(String username, String password) {
        Users user = usersMapper.findByUsername(username);
        return user != null && user.getPassword().equals(password);
    }
}

UsersController.java

java 复制代码
package com.sin.controller;

import com.sin.pojo.Users;
import com.sin.service.UserService;
import com.sin.service.UsersService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @createTime 2023/10/26 9:08
 * @createAuthor SIN
 * @use
 */
@Controller
public class UsersController {
    @Autowired
    private UsersService usersService;

    @GetMapping("/register1")
    public String showRegistrationForm(Model model) {
        model.addAttribute("user", new Users());
        return "register1";
    }

    @PostMapping("/register1")
    public String registerUser(@ModelAttribute("user") @Validated Users user, BindingResult result) {
        if (result.hasErrors()) {
            return "register1";
        }

        usersService.registerUser(user);
        return "redirect:/login";
    }

    @GetMapping("/login")
    public String showLoginForm() {
        return "login";
    }

   @PostMapping("/login")
    public String loginUser(@RequestParam("username") String username, @RequestParam("password") String password) {
        boolean isValid = usersService.loginUser(username, password);
        // 登录成功后返回到/dashboard页面
        if (isValid) {
            return "redirect:/dashboard";
        } else {  // 登录失败返回该页面
            return "login";
        }
    }
}

register1.html

html 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Registration</title>
</head>
<body>
<h1>Registration</h1>
<form th:action="@{/register1}" th:object="${user}" method="post">
    <div>
        <label>Username:</label>
        <input type="text" th:field="*{username}" required />
    </div>
    <div>
        <label>Password:</label>
        <input type="password" th:field="*{password}" required />
    </div>
    <button type="submit">Register</button>
</form>
</body>
</html>

login.html

html 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Login</title>
</head>
<body>
<h1>Login</h1>
<form th:action="@{/login}" method="post">
    <div>
        <label>Username:</label>
        <input type="text" name="username" required />
    </div>
    <div>
        <label>Password:</label>
        <input type="password" name="password" required />
    </div>
    <button type="submit">Login</button>
</form>
</body>
</html>

拦截功能

加入SpringSecurity

pom.xml

xml 复制代码
<!-- SpringSecurity -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

UserDetailsServiceImpl.java

java 复制代码
package com.sin.service.impl;

import com.sin.mapper.UserMapper;
import com.sin.mapper.UsersMapper;
import com.sin.pojo.Users;
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;

import java.util.ArrayList;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
  @Autowired
  private UsersMapper usersMapper;

    /**
    * 根据用户名加载用户信息
    */
  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      // 通过用户名从数据库中查询用户信息
    Users user = usersMapper.findByUsername(username);
      // 如果用户不存在,抛出异常
    if (user == null) {
      throw new UsernameNotFoundException("用户不存在");
    }
      // 创建并返回一个SpringSecurity的UserDetails对象用于身份验证和授权
    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());
  }
}

SecurityConfig.java

java 复制代码
package com.sin.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.EnableWebSecurity;
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;

/**
 * @createTime 2023/10/26 10:00
 * @createAuthor SIN
 * @use
 */
@Configuration // 表示这是这是一个配置类
@EnableWebSecurity // 启用web安全功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

    /**
    * 配置请求授权规则和相关的登录, 登出设置
    */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests() // 配置请求授权规则
                .antMatchers("/register1", "/login").permitAll() // 允许不需要认证即可访问的URL路径
                .anyRequest().authenticated()// 其他所有请求都需要进行身份认证
                .and()
                .formLogin() // 配置表单登录相关设置
                .loginPage("/login") // 自定义登录页面的URL路径
                .defaultSuccessUrl("/dashboard") // 登录成功后的默认跳转的页面
                .permitAll() // 允许所有用户访问登录页面
                .and() 
                .logout() // 配置登出相关设置
                .permitAll(); // 允许所有用户访问登录url路径
    }

    /**
    * 配置身份认证方式
    */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 配置自定义的userDetailsService实例,用户处理身份认证
        auth.userDetailsService(userDetailsService); 
    }

    
    @Bean
    public PasswordEncoder passwordEncoder() {
        // 返回BCryptPasswordEncoder实例,用于对密码进行加密和验证
        return new BCryptPasswordEncoder();
    }
}

UsersController.java

java 复制代码
  @Autowired
    private PasswordEncoder passwordEncoder;



@PostMapping("/register1")
public String registerUser(@ModelAttribute("user") @Validated Users user, BindingResult result) {
    if (result.hasErrors()) {
        return "register1";
    }
    String encodedPassword = passwordEncoder.encode(user.getPassword());
    user.setPassword(encodedPassword);

    usersService.registerUser(user);
    return "redirect:/login";
}

权限功能

sql

表中添加字段

sql 复制代码
alter table users add authority varchar(20) character set utf8mb4 default 'USER' comment '用户权限';

User.java

java 复制代码
public class Users {
    private Integer id;
    private String username;
    private String password;

    private String authority;

UserMapper.xml

xml 复制代码
<insert id="insertUser" parameterType="com.sin.pojo.Users">
    INSERT INTO users (username, password,authority) VALUES (#{username}, #{password},#{authority})
</insert>

UserDetailsServiceImpl.java

java 复制代码
package com.sin.service.impl;

import com.sin.mapper.UserMapper;
import com.sin.mapper.UsersMapper;
import com.sin.pojo.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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;

import java.util.ArrayList;
import java.util.List;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
  @Autowired
  private UsersMapper usersMapper;
    /**
    * 根据用户名加载用户信息
    */
  @Override
  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
      // 通过用户名从数据库中查询用户信息
    Users user = usersMapper.findByUsername(username);
      // 如果用户不存在,抛出异常
    if (user == null) {
      throw new UsernameNotFoundException("用户不存在");
    }

      // 存储用户的权限信息
    List<GrantedAuthority> authorities = new ArrayList<>();
      // 将用户的权限信息添加到列表中,
      // SimpleGrantedAuthority类表示用户的权限,
    authorities.add(new SimpleGrantedAuthority(user.getAuthority()));

    return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);

  }
}

SecurityConfig.java

java 复制代码
/**
* 配置HTTP请求的安全性
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .authorizeRequests() // 对请求进行授权的配置
            .antMatchers("/register1", "/login").permitAll() // 所有用户都可以访问
            .antMatchers("/**").hasAuthority("ADMIN")// 该路径具有ADMIN权限才能访问
            .anyRequest().authenticated()// 其他的路径需要进行身份认证
            .and() // 连接多个授权规则
            .formLogin() // 授权表单的相关设置
            .loginPage("/login") // 自定义的登录页面路径为/login
            .defaultSuccessUrl("/dashboard") // 登录成功后跳转的路径
            .permitAll() // 登录页面和登录请求路径都允许所有用户访问,即不需要进行身份验证
            .and() 
            .logout() // 配置登出的相关操作
            .permitAll(); // 登出请求路径允许所有用户访问,即不需要进行身份验证
}

register1.html

java 复制代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Registration</title>
</head>
<body>
<h1>Registration</h1>
<form th:action="@{/register1}" th:object="${user}" method="post">
    <div>
        <label>Username:</label>
        <input type="text" th:field="*{username}" required />
    </div>
    <div>
        <label>Password:</label>
        <input type="password" th:field="*{password}" required />
    </div>
    <div>
        <label>authoritie:</label>
        <input type="text" th:field="*{authority}" required />
    </div>
    <button type="submit">Register</button>
</form>
</body>
</html>
相关推荐
小码哥_常1 小时前
别再被误导!try...catch性能大揭秘
后端
无巧不成书02183 小时前
30分钟入门Java:从历史到Hello World的小白指南
java·开发语言
苍何3 小时前
30分钟用 Agent 搓出一家跨境网店,疯了
后端
ssshooter4 小时前
Tauri 2 iOS 开发避坑指南:文件保存、Dialog 和 Documents 目录的那些坑
前端·后端·ios
追逐时光者4 小时前
一个基于 .NET Core + Vue3 构建的开源全栈平台 Admin 系统
后端·.net
程序员飞哥4 小时前
90后大龄程序员失业4个月终于上岸了
后端·面试·程序员
zs宝来了5 小时前
Playwright 自动发布 CSDN 的完整实践
java
彭于晏Yan6 小时前
Redisson分布式锁
spring boot·redis·分布式
吴声子夜歌6 小时前
TypeScript——基础类型(三)
java·linux·typescript
GetcharZp6 小时前
Git 命令行太痛苦?这款 75k Star 的神级工具,让你告别“合并冲突”恐惧症!
后端