SpringSecurity初级入门

本篇文章将介绍

1.使用SpringSecurity默认账号密码登录

2.使用配置文件配置账号密码登录

3.使用配置类 设置账号 并设置权限

4.连接数据库,使用数据库中数据账号密码进行登陆

 

1.创建Boot项目 导入相应的依赖

2.配置文件

spring:
  devtools:
    restart:
      enabled: false  #开启热部署 true
     # additional-paths: src/main/java  #设置重启目录
     # exclude: WEB-INF/** 设置classpath目录下的WEB-INF文件夹内容修改不重启
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8
    hikari: # springboot 2.0 整合了hikari ,据说这是目前性能最好的java数据库连接池
      username: xxxx
      password: xxxx
  jpa:
    hibernate:
      ddl-auto: update  # 第一次建表create  后面用update,要不然每次重启都会新建表
    show-sql: true
    #配置文件中配置 登陆账号密码
#  security:
#    user:
#      name: admin
#      password: admin

#端口号配置  默认是8080
server:
  port: 8081

基本准备工作已经做好 下面编写第一个controller方法

一 . 使用SpringSecurity默认账号密码登录

package com.example.reviewsecurity.controller;

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

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
@RestController
@RequestMapping("/meetingFriends")
public class SecurityController {

    @GetMapping("/accost")
    public String firstTime(){
        return "hello,we haven't before,have we?";
    }
}

然后启动项目 会看到 控制台会打印 这样一串字符

这个就是SpringSecurity登陆时的密码passWord 每次都会不同哦  默认的userName  为user

在页面上访问controller中编写的路径http://localhost:8081/meetingFriends/accost   然后SpringSecurity进行拦截

成功输入之后即可进入页面

二.使用配置文件配置账号密码登录

将配置文件中的 注解解开即可

 配置文件中配置 登陆账号密码
security:
  user:
    name: admin
    password: admin

然后重启 项目 使用此账号登陆即可  其实不用重启 因为在配置文件中已经设置热部署

如果热部署不好使

IDEA配置

当我们修改了Java类后,IDEA默认是不自动编译的,而spring-boot-devtools又是监测classpath下的文件发生变化才会重启应用,所以需要设置IDEA的自动编译:

(1)File-Settings-Compiler-Build Project automatically

(2)ctrl + shift + alt + /,选择Registry,勾上 Compiler autoMake allow when app running

就OK啦

三 使用配置类 设置账号密码  并设置权限

创建配置类

package com.example.reviewsecurity.config;

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

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
@Configuration
@EnableWebSecurity //开启springSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password(passwordEncoder().encode("user")).roles("normal");
        auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("admin")).roles("manager");
    }

    @Bean //不可忘记加 否者此方法无效 依旧会报 java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

 

如果对设置账号时 你是这样设置的

 auth.inMemoryAuthentication().withUser("admin").password("admin").roles();

登陆时报错

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

原因:

从 Spring5 开始,强制要求密码要加密 Spring Security 中提供了 BCryptPasswordEncoder 密码编码工具,可以非常方便的实现密码的加密加盐,相同明文加密出来的结果总是不同,这样就不需要用户去额外保存的字段了,这一点比 Shiro 要方便很多。

 

设置权限

配置类

package com.example.reviewsecurity.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.prepost.PreAuthorize;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.annotation.PostConstruct;

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
@Configuration
@EnableWebSecurity //开启springSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启安全级别的权限控制  开启验证权限 prePostEnabled为true的时候会拦截标有@PreAuthorize的方法 验证权限
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password(passwordEncoder().encode("user")).roles("normal");
        auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder().encode("admin")).roles("manager");
    }

    @Bean //不可忘记加 否者此方法无效 依旧会报 java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

controller

package com.example.reviewsecurity.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;

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
@RestController
@RequestMapping("/meetingFriends")
public class SecurityController {

    @GetMapping("/accost")
    public String firstTime(){
        return "hello,we haven't before,have we?";
    }

    @GetMapping("/greet")
    @PreAuthorize("hasAnyRole('normal','manager')") //设置权限让指定的角色进行访问此方法,多个角色可用逗号隔开
    public String secondTime(){
        return "how are you doing?";
    }


    /**
     * 角色 normal 访问此方法时 因权限不足 页面会报错  There was an unexpected error (type=Forbidden, status=403).
     * */
    @GetMapping("/familiar")
    @PreAuthorize("hasAnyRole('manager')")
    public String thirtyTime(){
        return "hi,what's up?";
    }


}

当访问权限不足时 页面报错

四 连接数据库 使用数据 登陆

实体类

package com.example.reviewsecurity.domain;

import lombok.Data;

import javax.persistence.*;

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
@Entity
@Data
public class UserInfo {

    @Id    //主键
    @GeneratedValue  //自增
    private Long userId;
    private String userName;
    private String passWord;

    @Enumerated(EnumType.STRING)
    private Role role;
    public enum  Role{
        normal,manager;
    }
}

dao层

package com.example.reviewsecurity.dao;

import com.example.reviewsecurity.domain.UserInfo;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
public interface SecurityDao extends JpaRepository<UserInfo,Long> {
    UserInfo getUserInfoByUserName(String userName);
}

service层

package com.example.reviewsecurity.service;

import com.example.reviewsecurity.domain.UserInfo;

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
public interface SecurityService {
    UserInfo getUserInfoByUserName(String userName);
}

service实现类

package com.example.reviewsecurity.service.impl;

import com.example.reviewsecurity.dao.SecurityDao;
import com.example.reviewsecurity.domain.UserInfo;
import com.example.reviewsecurity.service.SecurityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
@Service
public class SecurityServiceImpl implements SecurityService {

    @Autowired
    SecurityDao securityDao;
    @Override
    public UserInfo getUserInfoByUserName(String userName) {
        return securityDao.getUserInfoByUserName(userName);
    }
}

数据初始化

package com.example.reviewsecurity.dataSource;

import com.example.reviewsecurity.dao.SecurityDao;
import com.example.reviewsecurity.domain.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
@Service
public class SecurityDataSource {

    @Autowired
    SecurityDao securityDao;

    @PostConstruct //当项目启动的时候  初始化数据
    public void dataInit(){
        UserInfo lili = new  UserInfo();
        lili.setUserName("lili");
        lili.setPassWord("lili");
        lili.setRole(UserInfo.Role.manager);
        securityDao.save(lili);
        UserInfo huahua = new  UserInfo();
        huahua.setUserName("huahua");
        huahua.setPassWord("huahua");
        huahua.setRole(UserInfo.Role.normal);
        securityDao.save(huahua);
    }
}

配置类

package com.example.reviewsecurity.config;

import com.example.reviewsecurity.domain.UserInfo;
import com.example.reviewsecurity.service.SecurityService;
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.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

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

/**
 * @Author xiang
 * @CreatTime 2020/4/17
 * @Describe
 */
@Component
public class UserDetail implements UserDetailsService {

    @Autowired
    SecurityService securityService;
    
    @Autowired
    PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        UserInfo userInfoByUserName = securityService.getUserInfoByUserName(userName);

        List<GrantedAuthority> role = new ArrayList<>();
        role.add(new SimpleGrantedAuthority("ROLE_"+userInfoByUserName.getRole().name()));
      //  User userDetail = new User(userInfoByUserName.getUserName(),userInfoByUserName.getPassWord(),role);
        User userDetail = new User(userInfoByUserName.getUserName(),passwordEncoder.encode(userInfoByUserName.getPassWord()),role);
        return userDetail;
    }
}

user的构造函数中的第三个参数角色是一个集合

编写完之后 在项目启动之前 注意   要注释掉 之前 配置文件中设置的权限账号 否则

页面报 Bad credentials

注释之后  根据数据库中相应的值进行登陆  即可

----------------------------------------------------------------------

项目启动流程

项目启动---初始化数据----登陆----走配置类根据userName获取userDetail----从userDetail中获取角色走controller方法进行验证

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值