spring security简单的权限访问控制

Posted 爱上口袋的天空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring security简单的权限访问控制相关的知识,希望对你有一定的参考价值。

1、在pom.xml文件中引入数据库的依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>kgf-java-learning</artifactId>
        <groupId>com.kgf.learning</groupId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../kgf-java-learning/pom.xml</relativePath>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.kgf.security</groupId>
    <artifactId>spring-security-demo</artifactId>
    <properties>
        <lombok.version>1.18.16</lombok.version>
        <fastjson.version>1.2.75</fastjson.version>
        <druid.version>1.2.2</druid.version>
        <mybatis-plus.version>3.4.1</mybatis-plus.version>
        <mysql.version>5.1.49</mysql.version>
    </properties>
    <dependencies>
        <!--引入mysql依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <!--引入mybatis-plus依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus.version}</version>
        </dependency>
        <!-- 引入druid连接池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--lombok 用来简化实体类-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.2.11.RELEASE</version>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2、在application.yaml文件中配置数据库连接

server:
  port: 8081

#spring:
#  security:
#    user:
#      name: admin
#      password: admin

spring:
  datasource:
    url: jdbc:mysql://192.168.1.13:3306/oss?userUnicode=true&characterEncoding=UTF-8&serverTimeZone=UTC
    username: root
    password: 897570
    driver-class-name: com.mysql.jdbc.Driver

mybatis-plus: #注意:延迟加载不能在开启debug后,不能点开list信息,甚至不能把鼠标移到上面。否则在debug下会默认执行关联查询。
  mapper-locations: classpath:/mappers/**/*.xml
  type-aliases-package: com.kgf.security

3、启动类SecurityApplication

package com.kgf.security;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@MapperScan(value = "com.kgf.security.mapper")
@SpringBootApplication
public class SecurityApplication {

    public static void main(String[] args) {

        SpringApplication.run(SecurityApplication.class,args);

    }

}

4、自定义的MyUserDetailsService

package com.kgf.security.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.kgf.security.mapper.UsersMapper;
import com.kgf.security.model.Users;
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 javax.annotation.Resource;
import java.util.List;

/***
 * spring security查询用户的时候会自动到这个类中去查找
 */
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {

    @Resource
    private UsersMapper usersMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        QueryWrapper<Users> usersQueryWrapper = new QueryWrapper<>();
        usersQueryWrapper.eq("username",username);
        Users users = usersMapper.selectOne(usersQueryWrapper);
        if (users==null){
            throw new UsernameNotFoundException("用户名不存在!");
        }
        //这里我们就不去查询数据库了,直接new一个对象
        List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        return new User(username,users.getPassword(),authorityList);
    }
}

5、创建UsersMapper

package com.kgf.security.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.kgf.security.model.Users;

public interface UsersMapper extends BaseMapper<Users> {
}

6、创建Users实体类

package com.kgf.security.model;

import lombok.Data;

@Data
public class Users {

    private Integer id;

    private String username;

    private String password;

}

7、创建SecurityConfig配置类

package com.kgf.security.config;

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

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;


    /***
     * 设置登录的用户
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这是使用内存的方式
//        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
//        String password = encoder.encode("123456");
//        auth.inMemoryAuthentication().withUser("test").password(password).roles("admin");
        //下面使用自定义接口实现类从数据库查询
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login.html")//登录页面设置
                .loginProcessingUrl("/user/login")//登录访问路径,这个不需要自己写controller,配置即可,这个是spring security自动完成
                .defaultSuccessUrl("/test/index").permitAll()//登录成功之后跳转的路径
                .and().authorizeRequests()
                .antMatchers("/","/test/hello","/user/login").permitAll()//设置这些路径可以直接访问,不需要认证
                .anyRequest().authenticated()
                .and().csrf().disable();//关闭csrf防护
    }

    /***
     * 注入PasswordEncoder到spring中
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

}

8、创建TestController

package com.kgf.security.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("test")
@RestController
public class TestController {


    @RequestMapping("hello")
    public String test(){
        return "hello security";
    }

    @RequestMapping("index")
    public String index(){
        return "hello index";
    }
}

9、创建我们的login.html

<!DOCTYPE html>
<!-- 需要添加
<html  xmlns:th="http://www.thymeleaf.org">
这样在后面的th标签就不会报错
 -->
<html  xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>xx</title>
</head>
<body>


<h1>表单提交</h1>
<!-- 表单提交用户信息,注意字段的设置,直接是*{} -->
<form action="/user/login"  method="post">
    <input type="text" name="username" />
    <input type="text" name="password" />
    <input type="submit" />
</form>
</body>
</html>

注意:这里面的用户名和密码必须是username和password,因为在spring security中是写死的,在spring security中存在一个UsernamePasswordAuthenticationFilter拦截器,如下:

 

10、插入数据库数据

11、测试

1)首先我们访问一下不需要认证的接口/test/hello

    

   没问题,直接访问

2)我们访问一下不需要认证的接口/test/index接口,应该被拦截直接跳转到登录页面

 输入我们数据库的用户名和密码:

 

成功! 

以上是关于spring security简单的权限访问控制的主要内容,如果未能解决你的问题,请参考以下文章

手把手教你如何使用Spring Security(下):访问控制

自己动手实现简单权限控制

Spring Security源码:权限访问控制是如何做到的?

Spring Security源码:权限访问控制是如何做到的?

基于Spring LDAP和Spring Security的用户认证和权限控制Web实现

Spring Security——基于表达式的权限控制