因为项目需要,第一次接触 Spring Security,早就听闻 Spring Security 功能强大但上手困难,学习了几天出入门道,特整理这篇文章希望能让后来者少踩一点坑(本文附带实例程序,请放心食用

本篇文章环境:SpringBoot 2.0 + Mybatis + Spring Security 5.0

源码地址:https://github.com/jitwxs/blog_sample

文章目录

一、导入依赖
二、创建数据库
三、准备页面
四、配置application.properties
五、创建实体、Dao、Service和Controller
  5.1 实体
  5.2 Dao
  5.3 Service
  5.4 Controller
六、配置SpringSecurity
  6.1 UserDetailsService
  6.2 WebSecurityConfig
七、运行程序

一、导入依赖

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

<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.1</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

二、创建数据库

一般权限控制有三层,即:用户<–>角色<–>权限,用户与角色是多对多,角色和权限也是多对多。这里我们先暂时不考虑权限,只考虑用户<–>角色

创建用户表sys_user

CREATE TABLE `sys_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建权限表sys_role

CREATE TABLE `sys_role` (
`id` int(11) NOT NULL,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建用户-角色表sys_user_role

CREATE TABLE `sys_user_role` (
`user_id` int(11) NOT NULL,
`role_id` int(11) NOT NULL,
PRIMARY KEY (`user_id`,`role_id`),
KEY `fk_role_id` (`role_id`),
CONSTRAINT `fk_role_id` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

初始化一下数据:

INSERT INTO `sys_role` VALUES ('', 'ROLE_ADMIN');
INSERT INTO `sys_role` VALUES ('', 'ROLE_USER'); INSERT INTO `sys_user` VALUES ('', 'admin', '');
INSERT INTO `sys_user` VALUES ('', 'jitwxs', ''); INSERT INTO `sys_user_role` VALUES ('', '');
INSERT INTO `sys_user_role` VALUES ('', '');

博主有话说:

这里的权限格式为ROLE_XXX,是Spring Security规定的,不要乱起名字哦。

三、准备页面

因为是示例程序,页面越简单越好,只用于登陆的login.html以及用于登陆成功后的home.html,将其放置在 resources/static 目录下:

(1)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>

博主有话说:

用户的登陆认证是由Spring Security进行处理的,请求路径默认为/login,用户名字段默认为username,密码字段默认为password

(2)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>

四、配置application.properties

在配置文件中配置下数据库连接:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
spring.datasource.username=root
spring.datasource.password=root #开启Mybatis下划线命名转驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true

五、创建实体、Dao、Service和Controller

5.1 实体

(1)SysUser

public class SysUser implements Serializable{
static final long serialVersionUID = 1L; private Integer id; private String name; private String password; // 省略getter/setter
}

(2)SysRole

public class SysRole implements Serializable {
static final long serialVersionUID = 1L; private Integer id; private String name; // 省略getter/setter
}

(3)SysUserRole

public class SysUserRole implements Serializable {
static final long serialVersionUID = 1L; private Integer userId; private Integer roleId; // 省略getter/setter
}

5.2 Dao

(1)SysUserMapper

@Mapper
public interface SysUserMapper {
@Select("SELECT * FROM sys_user WHERE id = #{id}")
SysUser selectById(Integer id); @Select("SELECT * FROM sys_user WHERE name = #{name}")
SysUser selectByName(String name);
}

(2)SysRoleMapper

@Mapper
public interface SysRoleMapper {
@Select("SELECT * FROM sys_role WHERE id = #{id}")
SysRole selectById(Integer id);
}

(3)SysUserRoleMapper

@Mapper
public interface SysUserRoleMapper {
@Select("SELECT * FROM sys_user_role WHERE user_id = #{userId}")
List<SysUserRole> listByUserId(Integer userId);
}

5.3 Service

(1)SysUserService

@Service
public class SysUserService {
@Autowired
private SysUserMapper userMapper; public SysUser selectById(Integer id) {
return userMapper.selectById(id);
} public SysUser selectByName(String name) {
return userMapper.selectByName(name);
}
}

(2)SysRoleService

@Service
public class SysRoleService {
@Autowired
private SysRoleMapper roleMapper; public SysRole selectById(Integer id){
return roleMapper.selectById(id);
}
}

(3)SysUserRoleService

@Service
public class SysUserRoleService {
@Autowired
private SysUserRoleMapper userRoleMapper; public List<SysUserRole> listByUserId(Integer userId) {
return userRoleMapper.listByUserId(userId);
}
}

5.4 Controller

@Controller
public class LoginController {
private Logger logger = LoggerFactory.getLogger(LoginController.class); @RequestMapping("/")
public String showHome() {
String name = SecurityContextHolder.getContext().getAuthentication().getName();
logger.info("当前登陆用户:" + name); return "home.html";
} @RequestMapping("/login")
public String showLogin() {
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角色";
}
}

博主有话说:

  • 如代码所示,获取当前登录用户:SecurityContextHolder.getContext().getAuthentication()

  • @PreAuthorize 用于判断用户是否有指定权限,没有就不能访问

六、配置SpringSecurity

6.1 UserDetailsService

首先我们需要自定义 UserDetailsService ,将用户信息和权限注入进来。

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

实际情况下,大多将 DAO 中的 User 类继承 org.springframework.security.core.userdetails.User 返回。

@Service("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private SysUserService userService; @Autowired
private SysRoleService roleService; @Autowired
private SysUserRoleService userRoleService; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Collection<GrantedAuthority> authorities = new ArrayList<>();
// 从数据库中取出用户信息
SysUser user = userService.selectByName(username); // 判断用户是否存在
if(user == null) {
throw new UsernameNotFoundException("用户名不存在");
} // 添加权限
List<SysUserRole> userRoles = userRoleService.listByUserId(user.getId());
for (SysUserRole userRole : userRoles) {
SysRole role = roleService.selectById(userRole.getRoleId());
authorities.add(new SimpleGrantedAuthority(role.getName()));
} // 返回UserDetails实现类
return new User(user.getName(), user.getPassword(), authorities);
}
}

6.2 WebSecurityConfig

该类是 Spring Security 的配置类,该类的三个注解分别是标识该类是配置类、开启 Security 服务、开启全局 Securtiy 注解。

首先将我们自定义的 userDetailsService 注入进来,在 configure() 方法中使用 auth.userDetailsService() 方法替换掉默认的 userDetailsService。

这里我们还指定了密码的加密方式(5.0 版本强制要求设置),因为我们数据库是明文存储的,所以明文返回即可,如下所示:

@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()
// 如果有允许匿名的url,填在下面
// .antMatchers().permitAll()
.anyRequest().authenticated()
.and()
// 设置登陆页
.formLogin().loginPage("/login")
// 设置登陆成功页
.defaultSuccessUrl("/").permitAll()
// 自定义登陆用户名和密码参数,默认为username和password
// .usernameParameter("username")
// .passwordParameter("password")
.and()
.logout().permitAll(); // 关闭CSRF跨域
http.csrf().disable();
} @Override
public void configure(WebSecurity web) throws Exception {
// 设置拦截忽略文件夹,可以对静态资源放行
web.ignoring().antMatchers("/css/**", "/js/**");
}
}

七、运行程序

注:如果你想要将密码加密,可以修改 configure() 方法如下:

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

---------------------

作者:Jitwxs
来源:CSDN
原文:https://blog.csdn.net/yuanlaijike/article/details/80249235

SpringBoot集成Spring Security(1)——入门程序的更多相关文章

  1. SpringBoot集成Spring Security入门体验

    一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ...

  2. SpringBoot集成Spring Security(6)——登录管理

    文章目录 一.自定义认证成功.失败处理 1.1 CustomAuthenticationSuccessHandler 1.2 CustomAuthenticationFailureHandler 1. ...

  3. SpringBoot集成Spring Security(2)——自动登录

    在上一章:SpringBoot集成Spring Security(1)——入门程序中,我们实现了入门程序,本篇为该程序加上自动登录的功能. 文章目录 一.修改login.html二.两种实现方式 2. ...

  4. SpringBoot集成Spring Security(5)——权限控制

    在第一篇中,我们说过,用户<–>角色<–>权限三层中,暂时不考虑权限,在这一篇,是时候把它完成了. 为了方便演示,这里的权限只是对角色赋予权限,也就是说同一个角色的用户,权限是 ...

  5. SpringBoot集成Spring Security(4)——自定义表单登录

    通过前面三篇文章,你应该大致了解了 Spring Security 的流程.你应该发现了,真正的 login 请求是由 Spring Security 帮我们处理的,那么我们如何实现自定义表单登录呢, ...

  6. SpringBoot集成Spring Security(7)——认证流程

    文章目录 一.认证流程 二.多个请求共享认证信息 三.获取用户认证信息 在前面的六章中,介绍了 Spring Security 的基础使用,在继续深入向下的学习前,有必要理解清楚 Spring Sec ...

  7. springboot集成spring security安全框架入门篇

    一. :spring security的简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下 ...

  8. SpringBoot集成Spring Security

    1.Spring Security介绍 Spring security,是一个强大的和高度可定制的身份验证和访问控制框架.它是确保基于Spring的应用程序的标准 --来自官方参考手册 Spring ...

  9. SpringBoot 集成Spring security

    Spring security作为一种安全框架,使用简单,能够很轻松的集成到springboot项目中,下面讲一下如何在SpringBoot中集成Spring Security.使用gradle项目管 ...

随机推荐

  1. MySQL for OPS 07:主从复制

    写在前面的话 对于企业而言,在互联网这一块其实最重要的是数据.保证数据的安全性,稳定性是作为运维人的基本工作职责.于是为了数据安全性,引进了数据备份,bin log 等.但这并不意味着有这些就足够了. ...

  2. DataTable 转List

    忘了出处   ,这个是转别人的 public class DataToList<T> where T : new() { /// <summary> /// 利用反射和泛型 / ...

  3. 在秉火STM32F429挑战者开发板上移植Huawei LiteOS指南

    昨天在B站上突然看到了一个短视频,是在正点原子的战舰V3开发板上移植华为的Huawei LiteOS操作系统,就是这个视频:看完鸿蒙OS发布会,试用华为的物联网操作系统Lite OS(B站),于是呢, ...

  4. tf.argmax()解析

    tf.argmax(input,axis)根据axis取值的不同返回每行或者每列最大值的索引. 代码如下: import tensorflow as tfimport numpy as npsess= ...

  5. Asp.Net MVC控制器获取视图传值几种方式

    前台表单(V:视图) @{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="v ...

  6. 使用IDEA创建Spring Boot项目

    第一步:根据1.2.3点鼠标哦: 第二步:点击Next 第三步:按红框框选,然后Next 第四步:选个保存路径,然后Next 第五步:点击Finish就大功告成了

  7. Excel解析工具easyexcel全面探索

    1. Excel解析工具easyexcel全面探索 1.1. 简介 之前我们想到Excel解析一般是使用POI,但POI存在一个严重的问题,就是非常消耗内存.所以阿里人员对它进行了重写从而诞生了eas ...

  8. 【Java】简体中文、繁体中文转换

    项目中用到繁体中文语言适配,目前已经有开源的框架可以将简体中文转换成繁体中文,在此基础上封装了一个工具类,可以直接将简体中文的strings.xml转换成繁体中文的strings.xml. 引用Jar ...

  9. AI2(App Inventor 2)离线版服务器(AI伴侣2.47版)

    提供这个版本的原因: 与app.gzjkw.net的源代码版本尽可能的接近,这样导入app.gzjkw.net源文件的时候不会有“该项目由新版App Inventor系统创建,我们仍然尝试将其加载,但 ...

  10. python_机器学习_最临近规则分类(K-Nearest Neighbor)KNN算法

    1. 概念: https://scikit-learn.org/stable/modules/neighbors.html 1. Cover和Hart在1968年提出了最初的临近算法 2. 分类算法( ...