Spring Boot 整合 Spring Security

1.建库

  a.创建 用户表、角色表、关系表

CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `sys_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `sys_user_role` (
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL
);

  b.初始化数据

INSERT INTO `sys_role` VALUES (‘1‘, ‘ROLE_ADMIN‘);
INSERT INTO `sys_role` VALUES (‘2‘, ‘ROLE_USER‘);

INSERT INTO `sys_user` VALUES (‘1‘, ‘admin‘, ‘123‘);
INSERT INTO `sys_user` VALUES (‘2‘, ‘test‘, ‘123‘);

INSERT INTO `sys_user_role` VALUES (‘1‘, ‘1‘);
INSERT INTO `sys_user_role` VALUES (‘2‘, ‘2‘);

COMMIT;

2.创建springboot工程

  a.选择Spring Web、JDBC API、MyBatis Framework、MySQL Driver、Spring Security、Thymeleaf,并手动添加 thymeleaf-extras-springsecurity5 依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <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>2.1.1</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--对Thymeleaf添加Spring Security标签支持-->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>
    </dependencies>

  b.编写 application.yml 配置

spring:
  # 服务名称
  application:
    name: springboot-security
  # mysql数据源
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    username: root
    password: 123456
  # thymeleaf热加载
  thymeleaf:
    cache=false: false

# 服务端口号
server:
  port: 8081

#开启Mybatis下划线命名转驼峰命名
mybatis:
  configuration:
    map-underscore-to-camel-case: true

  c.创建Entity实体类

    1)用户Entity

public class SysUser implements Serializable {

    //ID
    private Integer id;
    //用户名
    private String name;
    //密码
    private String password;

    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 getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

    2)角色Entity

public class SysRole implements Serializable {

    //ID
    private Integer id;
    //角色名称
    private String name;

    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;
    }
}

    3)用户-角色关系Entity

public class SysUserRole implements Serializable {

    //用户ID
    private Integer userId;
    //角色ID
    private Integer roleId;

    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public Integer getRoleId() {
        return roleId;
    }
    public void setRoleId(Integer roleId) {
        this.roleId = roleId;
    }
}

  d.创建 Mybatis 的 Mapper

    1)用户Mapper

@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)角色Mapper

@Mapper
public interface SysRoleMapper {

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

}

    3)用户-角色关系Mapper

@Mapper
public interface SysUserRoleMapper {

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

}

  e.创建Service

    1)用户Service

@Service
public class SysUserService {

    @Resource
    private SysUserMapper userMapper;

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

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

}

    2)角色Service

@Service
public class SysRoleService {

    @Resource
    private SysRoleMapper roleMapper;

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

}

    3)用户-角色Service

@Service
public class SysUserRoleService {

    @Resource
    private SysUserRoleMapper userRoleMapper;

    public List<SysUserRole> listByUserId(Integer userId) {
        return userRoleMapper.listByUserId(userId);
    }

}

  f.创建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(‘ADMIN‘)")
    public String printAdmin() {
        return "如果你看见这句话,说明你有ROLE_ADMIN角色";
    }

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

}

  g.配置SpringSecurity

    1)创建 Service 实现 UserDetailsService,将用户信息和权限注入进来

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Resource
    private SysUserService userService;

    @Resource
    private SysRoleService roleService;

    @Resource
    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);
    }

}

    2)创建 配置类 继承 WebSecurityConfigurerAdapter

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

    @Resource
    private CustomUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new PasswordEncoder() {
            @Override
            public String encode(CharSequence charSequence) {
//                return DigestUtils.md5DigestAsHex((charSequence.toString() + "salt").getBytes());
                return charSequence.toString();
            }

            @Override
            public boolean matches(CharSequence charSequence, String s) {
//                return s.equals(DigestUtils.md5DigestAsHex((charSequence.toString() + "salt").getBytes()));
                return s.equals(charSequence.toString());
            }
        });
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/", "/login").permitAll()//允许匿名访问的url
//                .antMatchers("/user/**").hasRole("USER")//允许指定角色访问的url
//                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()//其他所有url都需要验证
                .and()
                .exceptionHandling().accessDeniedPage("/403.html")// 权限不足自动跳转403
                .and()

                // 设置登陆页
                .formLogin().loginPage("/login")
                .failureUrl("/login?error")// 登陆失败页面(参数可供前端显示弹框)
//                .usernameParameter("username")// 自定义登陆用户名,默认为username
//                .passwordParameter("password")//自定义登陆密码参数,默认为password
                .and()

                //登出
                .logout()
                .logoutSuccessUrl("/");

        // 关闭CSRF跨域
        http.csrf().disable();
    }

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

}

    注:@Configuration 表示此类是个配置类,@EnableWebSecurity 表示开启SpringSecurity服务,@EnableGlobalMethodSecurity 表示开启SpringSecurity全局注解。

  h.创建 Html 文件

    1)templates 文件夹中创建 login.html 和 home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
    <h1>登陆</h1>
    <form method="post" action="/login">
        <div>
            <label>用户名:</label><input type="text" name="username">
        </div>
        <div>
            <label>密码:</label><input type="password" name="password">
        </div>
        <div>
            <button type="submit">立即登陆</button>
        </div>
    </form>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
    <!--匿名-->
    <div sec:authorize="isAnonymous()">
        未登录,点击 <a th:href="@{/login}">登录</a>
    </div>

    <!--登录-->
    <div sec:authorize="isAuthenticated()">
        <h1>登陆成功</h1>
        <p>用户名: <span sec:authentication="principal.username"></span></p>
        <p>权限: <span sec:authentication="principal.authorities"></span></p>
        <p>
            <span sec:authorize="hasRole(‘ADMIN‘)">这段话ADMIN能看到</span>
            <span sec:authorize="hasRole(‘USER‘)">这段话USER能看到</span>
        </p>
        <a href="/admin">检测ADMIN角色</a>
        <a href="/user">检测USER角色</a>
        <button onclick="location.href=‘/logout‘">退出登录</button>
    </div>
</body>
</html>

    2)在 static 文件夹中创建 403.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>权限不足</title>
</head>
<body>
    <h1>权限不足</h1>
</body>
</html>

3.启动服务登录 http://localhost:8081 测试效果

4.注意

  a.数据库中角色名称务必加上 “ROLE_” 前缀,authorities.add(new SimpleGrantedAuthority(role.getName())) 需要 “ROLE_”打头的的名称。

  b.hasRole(‘ADMIN‘) 需要去掉 “ROLE_” 前缀,而 hasAuthority("ROLE_ADMIN") 则需要加上“ROLE_” 前缀,即 hasRole(‘ADMIN‘)  与 hasAuthority("ROLE_ADMIN")  效果相同。

5.参考文档

  https://blog.csdn.net/yuanlaijike/article/details/80249235

  https://www.jianshu.com/p/dcf227d53ab5

原文地址:https://www.cnblogs.com/vettel0329/p/11772527.html

时间: 2024-11-09 04:58:41

Spring Boot 整合 Spring Security的相关文章

Spring Boot 整合Spring Data JPA

Spring Boot整合Spring Data JPA 1)加入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> &l

spring boot 整合spring Data JPA+Spring Security+Thymeleaf框架(上)

最近上班太忙所以耽搁了给大家分享实战springboot 框架的使用. 下面是spring boot 整合多个框架的使用. 首先是准备工作要做好. 第一  导入框架所需的包,我们用的事maven 进行对包的管理. 以上的举例是本人的H5DS的真实的后台管理项目,这个项目正在盛情融资中,各位多多捧点人场.关注一下软件发展的动态,说不定以后就是您的生活不可或缺的软件哟. 点击打开链接.闲话少说.现在切入正题. 第二,写点配置文件 第三,spring data -设计一个简单的po关系,这里需要下载一

Spring Boot整合Spring Security

Spring Boot对于该家族的框架支持良好,但是当中本人作为小白配置还是有一点点的小问题,这里分享一下.这个项目是使用之前发布的Spring Boot会员管理系统重新改装,将之前filter登录验证改为Spring Security 1. 配置依赖 Spring Boot框架整合Spring Security只需要添加相应的依赖即可,其后都是配置Spring Security. 这里使用Maven开发,依赖如下: <dependency> <groupId>org.spring

Spring Boot整合Spring Security总结

一.创建Spring Boot项目 引入Thymeleaf和Web模块以及Spring Security模块方便进行测试,先在pom文件中将 spring-boot-starter-security 的依赖注解掉测试. 二.创建几个用于测试的页面 <!DOCTYPE html><!--index页面--> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head&g

Spring Boot整合Spring MVC、Spring、Spring Data JPA(Hibernate)

一句话总结:Spring Boot不是新的功能框架,而是为了简化如SSH.SSM等等多个框架的搭建.整合及配置.使用Spring Boot 10分钟搭建起Spring MVC.Spring.Spring Data JPA(Hibernate)基础后台架构.基本零配置,全注解. 步骤一: 使用Spring Boot提供的网站生成maven项目及基础依赖.打开https://start.spring.io/网站,右侧输入想要的特性依赖.输入Web提供整合Spring MVC,输入JPA提供整合Spr

spring boot 整合spring security中spring security版本升级的遇到的坑

在spring security3.x的版本中 hasAnyRole这个方法不会对我们需要认证的身份前面加个前缀ROLE_,在3.x版本hasRole的源码如下 public final boolean hasAnyRole(String... roles) { Set<String> roleSet = getAuthoritySet(); for (String role : roles) { if (roleSet.contains(role)) { return true; } } r

Spring Boot 整合 Spring Cache + Redis

1.安装redis a.由于官方是没有Windows版的,所以我们需要下载微软开发的redis,网址:https://github.com/MicrosoftArchive/redis/releases b.解压后,在redis根目录打开cmd界面,输入:redis-server.exe redis.windows.conf,启动redis(关闭cmd窗口即停止) 2.使用 a.创建SpringBoot工程,选择maven依赖 <dependencies> <dependency>

Spring Kafka和Spring Boot整合实现消息发送与消费简单案例

本文主要分享下Spring Boot和Spring Kafka如何配置整合,实现发送和接收来自Spring Kafka的消息. 先前我已经分享了Kafka的基本介绍与集群环境搭建方法.关于Kafka的介绍请阅读Apache Kafka简介与安装(一),关于Kafka安装请阅读Apache Kafka安装,关于Kafka集群环境搭建请阅读Apache Kafka集群环境搭建 .这里关于服务器环境搭建不在赘述. Spring Kafka整合Spring Boot创建生产者客户端案例 创建一个kafk

Spring Boot --- 认识Spring Boot

在前面我们已经学习过Srping MVC框架,我们需要配置web.xml.spring mvc配置文件,tomcat,是不是感觉配置较为繁琐.那我们今天不妨来试试使用Spring Boot,Spring Boot让我们的Spring应用变的更轻量化.比如:你可以仅仅依靠一个Java类来运行一个Spring引用.你也可以打包你的应用为jar并通过使用java -jar来运行你的Spring Web应用. 一 Spring Boot简介 1.Spring Boot特点 开箱即用,提供各种默认配置来简