Spring Boot第五篇 -整合Spring Security

1.环境搭建:JDK1.8+IDEA+Mybatis

1.1 数据库搭建

1.2 映射类Person

package com.example.demo.pojo;

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

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    //get和set方法,构造器
    private String username;
    private  String password;
    private  String auth;
}

这里需要导入lombok依赖,

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

1.3 Mapper接口personMapper

package com.example.demo.Mapper;

import com.example.demo.pojo.Person;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Component;

import java.util.List;

@Mapper//表示Mapper类接口,表示创建Mapper时需要扫这个接口
@Component
public interface personMapper {
    //根据用户名查询用户
    public Person showuser(String name);

}

 1.4配置数据源.yml文件

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/book
    driver-class-name: com.mysql.cj.jdbc.Driver

1.5配置Mapper.xml文件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.example.demo.Mapper.personMapper">
    <select id="showuser" resultType="Person" parameterType="String">
        select * from t_user WHERE username=#{name}
    </select>

</mapper>

 注:resultType:表示返回类型

      id要与Mapper接口中的方法名相同

      parameterType是参数类型,要与方法中的参数类型相同,SQL语句中采用#{。。。}引用

      在SQL优化中不建议使用 select * 查询,注意namespace中的路径是Mapper接口的类,即              @Mapper注解所在类。

1.6 整合Mybatis和类(在.yml文件中)

mybatis:
  type-aliases-package: com.example.demo.pojo
  mapper-locations: classpath:mapper/*.xml

 注意接着行写,.yml文件要求很高,区分大小写,行与行之间不能空

1.7完整的.yml文件

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/book
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  type-aliases-package: com.example.demo.pojo
  mapper-locations: classpath:mapper/*.xml

2.java代码结构(三层)

web 层 web/servlet/controller

service 层 service  

dao 持久层 dao 

实体 bean 对象 pojo/entity

JavaBean 类 测试包 test

工具类 utils

分层的目的是为了解耦,降低代码的耦合度

2.1结构图

 

2.2config包--SecurityConfig类

package com.example.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;


import javax.sql.DataSource;

@EnableWebSecurity // 开启WebSecurity模式
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired//注入service层配置
    private UserDetailsService userDetailsService;

    @Override// 请求授权规则
    protected void configure(HttpSecurity http) throws Exception {

        // index所有人可以访问
        //add页面只能具有vip1角色访问
       //update页面只能具有vip2角色访问
        http.authorizeRequests().antMatchers("/index").permitAll()
                .antMatchers("/add").hasRole("vip1")
                .antMatchers ( "/update" ).hasRole ( "vip2" );

        //Security内置的登录页
        http.formLogin ();
        //开启记住我功能
        http.rememberMe();
        //开启注销功能
        http.logout ();

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //用数据库验证用户
           auth.userDetailsService ( userDetailsService ).passwordEncoder ( password() );

        //自定义用户
   /*  auth.inMemoryAuthentication().passwordEncoder ( new BCryptPasswordEncoder (  ) )
                .withUser("wang").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2");*/

    }

    @Bean
    public PasswordEncoder password(){
        //密码加密
        return  new BCryptPasswordEncoder ( );
    }
}

 这些方法在源码中有定义,需要看源码

 BCryptPasswordEncoder这部分的源码介绍我也没看懂,百度了一下,encode方法这个方法中先基于某种规则得到了一个盐值,然后在调用BCrypt.hashpw方法,传入明文密码和盐值salt。

 @EnableWebSecurity这个需要看下官方文档,看完照着写就行

注销的动作,起初我是自己写的,但总是报错,看了下源码,它把请求写好了

 2.3controller层--MyController

 

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MyController {
    @RequestMapping({"/","/index"})
    public String show(Model model){
            model.addAttribute ( "msg","错误" );
            return "index";
        }
      @RequestMapping("/add")
        public String add(){
        return "user/add";
        }

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

    @RequestMapping("/update")
        public String update(){
        return "user/update";
        }


}

注意:返回的是请求,不是路径。。。

2.4 service层--MyDetailsService

package com.example.demo.service;

import com.example.demo.Mapper.personMapper;
import com.example.demo.pojo.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("userDetailsService")
public class MyDetailsService implements UserDetailsService {
    @Autowired   //注入mapper配置信息
    private personMapper personMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Person showuser = personMapper.showuser ( username );
        System.out.println (showuser );
        if (showuser==null)
        {
            System.out.println ("不存在该用户");
        }

         
        List<GrantedAuthority> auths= AuthorityUtils.commaSeparatedStringToAuthorityList ( "vip1" );
        return new User ( showuser.getUsername (),new BCryptPasswordEncoder ().encode ( showuser.getPassword ()),auths );
    }
}

 loadUserByUsernam返回的是当前用户信息

 @Service("userDetailsService")注意名称要与SecurityConfig类中的@Autowired注入的要相同。不然@Autowired会报错。

3.静态页资源

3.1add.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
add
</body>
</html>

 3.2update.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
update
</body>
</html>

3.3index.html

<!DOCTYPE html>
<html lang="en"  xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
首页

<h4><a th:href="@{/add}">add</a></h4>
<h4><a th:href="@{/update}">update</a></h4>
<h4><a th:href="@{/logout}">注销</a></h4>

</body>
</html>

 登录页内置了,故当前登录页没啥用。。。

如果运行名称没在数据库找到时,运行会报空指针,但程序时对的,我没有写处理。。。

类似

 而且我数据库也没加上角色,只实现了验证登录,角色的话就是表多个属性,感兴趣可以自己完善一下。shiro和Security流行的两大安全框架写完了。。。推荐看狂神的博客。。。

4.完整依赖

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

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

		<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.2.1</version>
		</dependency>

		<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>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Amo@骄纵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值