Spring-Security

Posted Mr_XY

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring-Security相关的知识,希望对你有一定的参考价值。

概述

  1. 认证(你是谁,户/设备/系统
  2. 验证(你能干什么,也叫权限控制/授权,允许执行的操作)
  3. 基于Filter , Servlet, AOP实现身份认证和权限验证

使用

入门案例

1、新建工程,导入依赖

<!--spring-security相关依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2、配置访问地址,启动测试,获得秘钥

登陆名:user

密码:查看日志

获得秘钥

3、小结

使用AOP做了拦截,拦截后再访问的servlet

security相关配置

自定义用户名和密码

在Application.yml 中配置文件上的security的user和password

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

关闭验证

在启动类的注解中,排除安全验证,使用内存中的用户信息

关闭验证

使用内存中的账户

使用类WebSecurityConfigurerAdapter控制安全管理内容

  1. 自定义类继承WebSecurityConfigurerAdapter,声明是个配置类、开启WebSecurity
  2. 重写configure方法
  3. 在SpringSecurity_v5.0版本中,密码必须使用一个加密方式
  4. 构建一个方法创建一个BCrypt加密类,用于加密操作(BCrypt跨平台)
@Configuration
@EnableWebSecurity
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
				// 得到一个加密类,
        PasswordEncoder passwordEncoder = passwordEncoder();
        auth.inMemoryAuthentication().withUser("zhangsan").password(passwordEncoder.encode("zhangsan")).roles();
        auth.inMemoryAuthentication().withUser("lisi").password(passwordEncoder.encode("lisi")).roles();
        auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder.encode("admin")).roles();
    }
		// 构建一个方法创建一个加密类,放入容器中
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

使用数据库的账户

1、导入依赖

<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>
<!--spring-jpa依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.4.5</version>
</dependency>

2、封装对象,创建一个实体类,初始化数据 使用JPA连接数据库

3.1、创建一个实体类

package com.study.entity;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
@Data
public class UserInfo {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;
    private String username;
    private String password;
    private String role;
}

3.2、创建一个dao

package com.study.dao;

import com.study.entity.UserInfo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserInfoDao extends JpaRepository<UserInfo, Long> {
    UserInfo findByUsername(String name);
}

3.3、创建service层的类 接口和实现类

package com.study.service;
import com.study.entity.UserInfo;

public interface UserInfoService {
    UserInfo findUserInfo(String username);
}
package com.study.service.impl;

import com.study.dao.UserInfoDao;
import com.study.entity.UserInfo;
import com.study.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    UserInfoDao userInfoDao;

    public UserInfo findUserInfo(String username) {
        UserInfo userInfo = userInfoDao.findByUsername(username);
        return userInfo;
    }
}

3.4、配置数据库连接信息

spring.datasource.url=jdbc:mysql://8.129.121.241:3306/springsecurity?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=xxyy
spring.datasource.password=xxYY11..
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring-data-jpa
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.database=mysql

3.5、初始化数据库数据

package com.study.init;

import com.study.dao.UserInfoDao;
import com.study.entity.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class JdbcInit {
    @Autowired
    private UserInfoDao userInfoDao;

    @PostConstruct
    public void init() {
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("lisi");
        userInfo.setPassword(passwordEncoder.encode("lisi"));
        userInfo.setRole("normal");
        userInfoDao.save(userInfo);
    }
}

3.6、查询数据库,构造一个User对象,用于框架中使用

package com.study.provider;

import com.study.dao.UserInfoDao;
import com.study.entity.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class MyUserDetailService implements UserDetailsService {
    @Autowired
    private UserInfoDao userInfoDao;
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user=null;
        UserInfo userInfo=null;
        if(username!=null){
            userInfo = userInfoDao.findByUsername(username);
            if (userInfo!=null){
                List<GrantedAuthority> list=new ArrayList<GrantedAuthority>();
                GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_"+userInfo.getRole());
                list.add(authority);
                user=new User(userInfo.getUsername(),userInfo.getPassword(),list);
            }
        }
        return user;
    }
}

4、编写配置类,将通过数据库得到的User对象,进行角色配置

package com.study.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;

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

5、添加Controller,最后测试验证,注意将添加数据库信息的注解注释掉

package com.study.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @GetMapping(value = "/hello")
    public String hello() {
        return "hello spring-security";
    }

    @RequestMapping(value = "/hellouser")
    @PreAuthorize(value = "hasAnyRole(\'ROLE_admin\',\'ROLE_normal\')")
    public String helloUser() {
        return "hello spring-security have normail Admin role";
    }

    @RequestMapping(value = "/helloadmin")
    @PreAuthorize(value = "hasAnyRole(\'ROLE_admin\')")
    public String helloAdmin() {
        return "hello spring-security have Admin role";
    }
}

踩坑

所有的权限都要加上 “ROLE_” 作为前缀

未完待续

以上是关于Spring-Security的主要内容,如果未能解决你的问题,请参考以下文章

了解 spring-security 上的 requestMatchers()

Spring-Security:认证后调用方法

如何使用spring-security通过用户名和密码登录?

Spring-security-3 浏览器后退按钮问题

Spring-security 的 CORS 问题

spring-security框架