本篇文章将介绍
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方法进行验证