Spring-Security连接数据库

Spring Security连接数据库

我们先随便创建一个数据库

导入我们security的依赖

 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>


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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>


        <!--引入mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.1</version>
        </dependency>

        <!--mqsql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <!--引入jdbc、-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>


        <!--引入模板引擎-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

我创建的是一个web项目,我还用了thymeleaf模板引擎,用于后的界面的跳转,因为thymeleaf它是idea推荐的,idea默认比较点多,但是真的写项目的时候,我不推荐thymeleaf,它很坑,反正我被坑过,写一些简单的跳转还可以,因为thymeleaf它的界面访问直接就给我们配置了一个默认路径classpath:/templates 我们只需要把我们创建的页面放进templates就好

然后我们创建一个实体类

package com.kuang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @ClassName User
 * @Description TODO
 * @Author ht
 * @Date 2020/8/20 10:23
 * @Version 1.0
 **/

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

  private  int id;

  private String username;

  private String password;

  private  String limit;


}

Security它不用写那个service层的接口,我们在添加进入我们自己的项目的时候我们可以单独创建一个Service的实现类用于Security,因为Security的实现类他是直接继承了UserDetailsService的接口,我们是直接重写它的loadUserByUsername方法就好
在这里插入图片描述
这就是我的文件的结构路径,根本没有service接口

接下来我们写service的实现类serviceimpl

@Service
//重写UserDetailsService的loadUserByUsername方法
public class UserDetailsServiceImpl implements UserDetailsService {

  @Autowired
  UserMapper mapper;

  @Autowired
  PasswordEncoder passwordEncoder;


  @Override

  public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
      User user =mapper.selectlimit(name);
      if (user==null){
        return null;
      }else {
        //创建一个权限的集合
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        //添加获取权限
        authorities.add(new SimpleGrantedAuthority(user.getLimit()));
        //把对象信息(用户名,密码,权限)存入对象,返回该对象,controller层直接调用
        org.springframework.security.core.userdetails.User user2 =new org.springframework.security.core.userdetails.User(user.getUsername(), passwordEncoder.encode(user.getPassword()), authorities);
        System.out.println("管理员信息:"+user.getUsername()+"   "+passwordEncoder.encode(user.getPassword())+"  "+user2.getAuthorities());
        return user2;
      }

  }
}

因为我是直接连接的数据库,所有这边我讲解一下,先把Mapper层写下来

@Mapper
@Repository
public interface UserMapper {

  public User selectlimit(String username);

}//

还有我们与Mapper层相映射的mapper.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.kuang.mapper.UserMapper">

    <resultMap id="user" type="com.kuang.pojo.User">
        <result property="id" column="id"/>
        <result property="username" column="name"/>
        <result property="password" column="password"/>
        <result property="limit" column="limit"/>
    </resultMap>



<!-- 获取权限-->
    <select id="selectlimit" resultMap="user">
        select * from  user  where  name=#{username};
    </select>

</mapper>

以及我们的Controller层

package com.kuang.controller;

import com.kuang.serviceimpl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName HelloWorld
 * @Description TODO
 * @Author ht
 * @Date 2020/8/12 16:45
 * @Version 1.0
 **/

@Controller
public  class HelloController{
  @Autowired
  UserDetailsServiceImpl userDetailsService;

  @GetMapping("/user")
  public String success(String name){
//    userDetailsService.loadUserByUsername(name);
    return "success";
  }

  @GetMapping("/root")
  public String vip(String name){
//    userDetailsService.loadUserByUsername(name);
    return "vip";
  }

  @GetMapping("/not")
  public String not(String name) {
    userDetailsService.loadUserByUsername(name);
    return "not";
  }

}

Controller层就是一些界面的跳转,不用在意这些

还有就是我们的首页,

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
================================
<hr>
<a th:href="@{/user}" th:text="user"></a>
<a th:href="@{/root}" th:text="vip"></a>

</body>
</html>

我们要让有user权限的进入user界面,有root权限的进入vip界面,注意啦这个只是一个路径,不是权限,权限我们的在config配置类中配置

Security的配置类是特别特别重要的东西,它里面写了认证以及授权

package com.kuang.config;


import com.kuang.serviceimpl.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @ClassName SecurityConfig
 * @Description TODO
 * @Author ht
 * @Date 2020/8/12 16:57
 * @Version 1.0
 **/
@EnableWebSecurity
//WebSecurityConfigurerAdapter自定义的security策略
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  //链式编程
  @Override
  //授权
  protected void configure(HttpSecurity http) throws Exception {
    //super.configure(http);
    //请求授权规则
    http.authorizeRequests()
      .antMatchers("/").permitAll()
      .antMatchers("/user").hasRole("USER")
      .antMatchers("/root").hasRole("ROOT");

    //没有权限自动跳转到登陆页(自带登录页)
    //默认是username,password
    //usernameParameter("user").passwordParameter("pwd").loginPage("/login");设置字段名以及跳转的接口
    http.formLogin();
  }

   /*
    认证规则
     */

  @Autowired
  UserDetailsServiceImpl userDetailsService;

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

  //在这里完成获得数据库中的用户信息
  //密码一定要加密
  //认证
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
  }
}

这里面我做了很多的注释,大家应该看得懂,但是我还是讲一下,虽然我也是初学者,增加记忆吧

现在我们需要的东西都写完了。。。。额还有一个yaml配置文件,

spring:
  datasource:
    username: 数据库用户名
    password: 数据库密码
    url: jdbc:mysql:"数据库的url:数据库"?serverTimezone=UTC&characterEncoding=UTF-8&userUnicode=true&autoReconnect=true
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
	#扫描配置mapper.xml的配置文件
  mapper-locations: classpath:mybatis/*.xml
  #设置别名,在mapper.xml中使用
  type-aliases-package: com.kuang.pojo

下面我们来好好理一理

我们访问我们的接口,它没有权限那么它就会直接访问了security自带的登陆界面,需要我们登陆用户验证

  //没有权限自动跳转到登陆页(自带登录页)
    //默认是username,password
    //usernameParameter("user").passwordParameter("pwd").loginPage("/login");设置字段名以及跳转的接口
    http.formLogin();

我们只需要开启它,不过好像security好像会自带开启,可以试试

大家是不是很纳闷,我们访问页面的时候我们并没有访问什么方法啊,我们是直接返回的一个界面呀,应该就不管security的事情啊,但是我们的给Securitry配置了confg纳闷它就会启动,具体的大家可以去看源码,它就会生效,而他生效,大家可以看到

  /*
    认证规则
     */

  @Autowired
  UserDetailsServiceImpl userDetailsService;

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

  //在这里完成获得数据库中的用户信息
  //密码一定要加密
  //认证
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
  }
}

在这堆代码里我们是不是可以看到一个很熟悉的东西,那就是我们的重写的UserDetailsServic接口的实现类,我们将其注入了这个类中,使用它,然后回到我们的UserDetailsServiceImpl实现类又注入了UserMapper,UserMapper又映射了UserMapper.xml文件,这样是不是就把我们的数据库连上了,但是注意了,密码必须加密,加密过后,ok就差不多了

我们继续说逻辑

 public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
      User user =mapper.selectlimit(name);
      if (user==null){
        return null;
      }else {
        //创建一个权限的集合
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        //添加获取权限
        authorities.add(new SimpleGrantedAuthority(user.getLimit()));
        //把对象信息(用户名,密码,权限)存入对象,返回该对象,controller层直接调用
        org.springframework.security.core.userdetails.User user2 =new org.springframework.security.core.userdetails.User(user.getUsername(), passwordEncoder.encode(user.getPassword()), authorities);
        System.out.println("管理员信息:"+user.getUsername()+"   "+passwordEncoder.encode(user.getPassword())+"  "+user2.getAuthorities());
        return user2;
      }

我们通过传入的name查询到我们的对象user它实体类User定义的,这里有一个很严肃的问题,就是loadUserByUsername这个方法,它只能接收一个参数,而且它里面自带了一个实体类User,我就着了道,但是我没改,我想给大家提个醒所有我用的这样的

org.springframework.security.core.userdetails.User user2 =new org.springframework.security.core.userdetails.User(user.getUsername(), passwordEncoder.encode(user.getPassword()), authorities);

loadUserByUsername的这个User类,有三个参数,username,password,以及authorities(权限),我们这边都是通过我们自己通过查询得到的对象user来传入数据
我们将数据传入进去,然后那边调用验证就好
有一个十分十分值得注意的地方超级坑,就是它的这个权限,你必须在你的权限前面加一个ROLE_就是这样
在这里插入图片描述
然后你在Config里面进行认证的时候它才会人,不然就是403,我试过很多次,在网上也看了很多东西,都没搞出个所以然,好啦,大部门就都讲完了

可以大家一看很多觉得比较乱,但是自己看了我觉得还是很不错的

写了博客,有全面仔细了解了一遍,自己感觉收货超大;

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值