SpringBoot 整合Spring Security第一章

本文详细介绍了如何在Spring Boot项目中使用Spring Security进行权限控制,包括依赖添加、数据库表设计、页面配置、实体与服务层创建及Spring Security核心配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


文章目录

前言:AuthenticationProvider认证是由 AuthenticationManager 来管理的,但是真正进行认证的是
AuthenticationManager 中定义的
AuthenticationProvider。AuthenticationManager 中可以定义有多个
AuthenticationProvider。当我们使用 authentication-provider 元素来定义一个
AuthenticationProvider 时,如果没有指定对应关联的 AuthenticationProvider 对象,Spring
Security 默认会使用 DaoAuthenticationProvider。DaoAuthenticationProvider
在进行认证的时候需要一个 UserDetailsService 来获取用户的信息
UserDetails,其中包括用户名、密码和所拥有的权限等。所以如果我们需要改变认证的方式,我们可以实现自己的
AuthenticationProvider;如果需要改变认证的用户信息来源,我们可以实现 UserDetailsService。

1、pom文件中添加依赖

1、pom文件中添加依赖

导入 spring-boot-starter-security 依赖,在 SpringBoot 2.0 环境下默认使用的是 5.0 版本。Springboot版本为2.1.6

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

    <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-security</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>
    </dependency>
</dependencies>

2、创建对应的user、role、user_role表

一般权限控制有三层,即:用户<–>角色<–>权限,用户与角色是多对多,角色和权限也是多对多,第一章我们先考虑用户和角色

1)、创建用户表(user)

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

2)、创建角色表role:

CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL,
  `nameZh` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

3)、创建用户角色关系表user_role:

CREATE TABLE `user_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,
  `rid` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

初始化各个表数据供测试使用

INSERT INTO `user_role` VALUES (1,'1', '1');
INSERT INTO `user_role` VALUES (2,'2', '2');

INSERT INTO `role` VALUES ('1', 'ROLE_admin','管理员');
INSERT INTO `role` VALUES ('2', 'ROLE_user','普通用户');

INSERT INTO `user` VALUES ('1', 'admin', '123');
INSERT INTO `user` VALUES ('2', 'zhao', '123');

SpringSecurity规定权限格式为ROLE_xxx,一定要注意!!

3、登录页面和主页面

因为是比较简单的security程序,所以页面比较简单登录完成之后跳到home页面,页面位置在resource/static目录下:
login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陆</title>
</head>
<body>
<h1>登陆</h1>
<form method="post" action="/login">
    <div>
        用户名:<input type="text" name="username">
    </div>
    <div>
        密码:<input type="password" name="password">
    </div>
    <div>
        <button type="submit">立即登陆</button>
    </div>
</form>
</body>
</html>

home.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>登陆成功</h1>
<a href="/admin">检测ROLE_ADMIN角色</a>
<a href="/user">检测ROLE_USER角色</a>
<button onclick="window.location.href='/logout'">退出登录</button>
</body>
</html>

4、配置application.properties

配置文件中简单配置数据库信息

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost/chapter03?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root

mybatis.configuration.map-underscore-to-camel-case=true

5、创建entity、dao、service、controller

1)创建对应的实体User、Role、UserRole

public class User implements Serializable {

    private Integer id;

    private String username;

    private String password;

     //getset方法省略
}

public class Role implements Serializable {

    private Integer id;

    private String name;

    private String nameZh;
     //getset方法省略
}

public class UserRole implements Serializable {

    private Integer id;

    private Integer uid;

    private Integer rid;
    //getset方法省略
}

2)、创建对应的dao层UserMapper、RoleMapper、UserRoleMapper

@Mapper
public interface UserMapper {

    @Select("SELECT * FROM user WHERE id = #{id}")
    User selectById(Integer id);

    @Select("SELECT * FROM user WHERE username = #{name}")
    User selectByName(String name);
}

@Mapper
public interface RoleMapper {

    @Select("SELECT * FROM role WHERE id = #{id}")
    Role selectById(Integer id);
}

@Mapper
public interface UserRoleMapper {

    @Select("SELECT * FROM user_role WHERE uid = #{uid}")
    List<UserRole> listByUseId(Integer uid);
}

3)、创建对应的service:UserService 、RoleService 、UserRoleService

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public User selectById(Integer id) {
        return  userMapper.selectById(id);
    }

    public User selectByName(String name) {
        return userMapper.selectByName(name);
    }
}

@Service
public class RoleService {

    @Autowired
    private RoleMapper roleMapper;

    public Role selectById(Integer id) {
        return roleMapper.selectById(id);
    }
}

@Service
public class UserRoleService {

    @Autowired
    private UserRoleMapper userRoleMapper;

    public List<UserRole> seletListByUserId(Integer uid) {
        return userRoleMapper.listByUseId(uid);
    }
}

4)、创建Controller

@Controller
public class LoginController {

    @RequestMapping("/")
    public String showHome() {
        //获取当前用户名
        String name = SecurityContextHolder.getContext().getAuthentication().getName();
        System.out.println("当前用户为:------>" + name);
        return "home.html";
    }

    @RequestMapping("/login")
    public String login() {
        return "login.html";
    }

    @RequestMapping("/admin")
    @ResponseBody
    @PreAuthorize("hasRole('ROLE_admin')") //判断用户是否有指定权限
    public String printAdmin() {
        return "如果你看见这句话,说明你有ROLE_admin角色";
    }

    @RequestMapping("/user")
    @ResponseBody
    @PreAuthorize("hasRole('ROLE_user')")
    public String printUser() {
        return "如果你看见这句话,说明你有ROLE_user角色";
    }
}

6、配置SpringSecurity

1)、 UserDetailsService

实现UserDetailsService 接口,将用户信息和权限注入进来,需要重写 loadUserByUsername 方法,参数是用户输入的用户名。返回值是UserDetails,这是一个接口,一般使用它的子类org.springframework.security.core.userdetails.User,它有三个参数,分别是用户名、密码和权限集。

@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private UserRoleService userRoleService;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        User user = userService.selectByName(username);
        // 判断用户是否存在
        if(user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }

        // 添加角色
        List<UserRole> userRoles = userRoleService.seletListByUserId(user.getId());
        for (UserRole userRole:userRoles) {
            Role role = roleService.selectById(userRole.getRid());
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }

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

2)、WebSecurityConfig

该类是 Spring Security 的核心配置类,该类的三个注解分别:

@Configuration//该类是配置类
@EnableWebSecurity//开启 Security 服
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启全局 Securtiy 注解。
具体实现:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
                return charSequence.toString();
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
                return s.equals(charSequence.toString());
            }
        });
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin().loginPage("/login")
                // 设置登陆成功页
                .defaultSuccessUrl("/").permitAll()
                .and()
                // 自定义登陆用户名和密码参数,默认为username和password
                // .usernameParameter("username")
                //  .passwordParameter("password")
                .logout()
                .permitAll();
        http.csrf().disable();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        // 设置拦截忽略文件夹,可以对静态资源放行
        web.ignoring().antMatchers("/css/**", "/js/**");
    }

}

程序启动成功就可以分别登陆,查看此用户属于哪种权限
​​
鸣谢: https://blog.youkuaiyun.com/yuanlaijike/article/details/80249235

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值