引入依赖
<!-- 引入springsecurity-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
设置用户名和密码
方式一配置文件application.properties
spring.security.user.name=xuliangjie
spring.security.user.password=123456
方式二配置类(配置类和配置文件同时设置,配置类生效)
package com.xu.securitydemo1.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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
//第二种方式设置用户名和密码配置类
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//继承这个类,需要重写父类的方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//对密码进行加密
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode("123");
//用auth设置用户名和密码
//inMemoryAuthentication()放入内存,设置用户名,设置密码,设置权限
auth.inMemoryAuthentication().withUser("lucy").password(password).roles("admin");
}
//PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
}
方式三自定义实现类(最实用,查数据库)
配置类和配置文件都写,配置类生效
这里演示的代码没有进行用户名检验,只要密码正确都能登录
以下是配置类
package com.xu.securitydemo1.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.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 SecurityConfigByself extends WebSecurityConfigurerAdapter {
//注入userdetailsservice 实现类
@Autowired
private UserDetailsService userDetailsService;
//继承这个类,需要重写父类的方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
//PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
}
以下是实现类
package com.xu.securitydemo1.service;
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")//取别名,和自定义配置类注入的名字对应(也可以不写@Autowired会默认先根据类型匹配,再根据名字)
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//用户名,密码,权限集合(实际查数据库得到)
String name = "marry";
String password = new BCryptPasswordEncoder().encode("123");
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
return new User(name,password,auths);
}
}
******************************************************************************************************
方式三查询数据库实现
1.
#数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/securitydemo?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
2.实体类
package com.xu.securitydemo1.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
public class User {
//private int id 不包含null,Integer可以包含为null的值
private Integer id;
private String username;
private String password;
}
3.mapper
package com.xu.securitydemo1.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xu.securitydemo1.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseMapper<User> {
}
4.service
package com.xu.securitydemo1.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xu.securitydemo1.mapper.UserMapper;
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")//取别名,和自定义配置类注入的名字对应(也可以不写@Autowired会默认先根据类型匹配,再根据名字)
public class MyUserDetailsService implements UserDetailsService {
//用autowired需要在UserMapper加上repository,不加repository需要用resource
//resource根据名称注入,Autowired根据类型注入
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//String s前端传过来一个用户名,根据用户名去查数据库
//我理解的是User是一个关键字之类的,所以自动变成全路径
QueryWrapper<com.xu.securitydemo1.entity.User> wrapper = new QueryWrapper<>();
wrapper.eq("username", s);
com.xu.securitydemo1.entity.User user = userMapper.selectOne(wrapper);
//判断
if (user == null) {
throw new UsernameNotFoundException("用户名不存在");
}
//用户名,密码,权限集合(实际查数据库得到)
String username = user.getUsername();
String password = new BCryptPasswordEncoder().encode(user.getPassword());
//权限集合我在数据库还没写,用这个测试
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
return new User(username,password,auths);
}
}
5.启动类
package com.xu.securitydemo1;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//扫描mapper包去找到实现类
@MapperScan(basePackages = {"com.xu.securitydemo1.mapper"})//没有写mapper的实现类,basemapper里封装了实现类,basemapper的sql语句在一个枚举类里SqlMethod
public class Securitydemo1Application {
public static void main(String[] args) {
SpringApplication.run(Securitydemo1Application.class, args);
}
}
*********************************************************************************************
自定义登录页面
写在第三种方式的配置类里
package com.xu.securitydemo1.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 SecurityConfigByself extends WebSecurityConfigurerAdapter {
//注入userdetailsservice 实现类
@Autowired
private UserDetailsService userDetailsService;
//继承这个类,需要重写父类的方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
//PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
//自定义登录页面
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //自定义登录页面
.loginPage("/login.html") //自定义页面地址
.loginProcessingUrl("/user/login") //登录提交表单之后访问的路径进行UserDetailsService的验证
.defaultSuccessUrl("/test/index").permitAll() //登录成功跳转到的路径
.and().authorizeRequests()
.antMatchers("/", "/test/hello", "/user/login").permitAll() //设置哪些路径不需要登录认证可以直接访问
.anyRequest().authenticated() //表示所有请求都需要认证
.and().csrf().disable();//关闭csrf防护
}
}
********************************************************************************************************
权限访问
增删改查权限:
hasAuthority()方法只能写一个权限
//表示当前登录的用户只有admins权限的才能访问/test/index
.antMatchers("/test/index").hasAuthority("admins")
hasAnyAuthority()方法有任一权限都可以访问
//hasAnyAuthority()方法有任一权限都可以访问
.antMatchers("/test/index").hasAnyAuthority("admins,manager")
用户的角色权限:
hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale
//hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale
.antMatchers("/test/index").hasRole("sale")
hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_
//4.hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_
.antMatchers("/test/index").hasAnyRole("sale,role")
***********************************************************************************************
配置由于没有权限跳转的页面
package com.xu.securitydemo1.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 SecurityConfigByself extends WebSecurityConfigurerAdapter {
//注入userdetailsservice 实现类
@Autowired
private UserDetailsService userDetailsService;
//继承这个类,需要重写父类的方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
//PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
//自定义登录页面
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //自定义登录页面
.loginPage("/login.html") //自定义页面地址
.loginProcessingUrl("/user/login") //登录提交表单之后访问的路径进行UserDetailsService的验证
.defaultSuccessUrl("/test/index").permitAll() //登录成功跳转到的路径
.and().authorizeRequests()
.antMatchers("/", "/test/hello", "/user/login").permitAll() //设置哪些路径不需要登录认证可以直接访问
//表示当前登录的用户只有admins权限的才能访问/test/index
//1.hasAuthority()方法只能写一个权限
//.antMatchers("/test/index").hasAuthority("admins")
//2.hasAnyAuthority()方法有任一权限都可以访问
//.antMatchers("/test/index").hasAnyAuthority("admins,manager")
//3.hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale
//.antMatchers("/test/index").hasRole("sale")
//4.hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_
.antMatchers("/test/index").hasAnyRole("xxx")
.anyRequest().authenticated()
.and().csrf().disable();//关闭csrf防护
//配置没有权限跳转的页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
}
}
**************************************************************************************************************
授权注解
@Secured({"ROLE_sale"})
在启动类上加上@EnableGlobalMethodSecurity(securedEnabled = true)//开启注解配置权限
//这个注解的含义是当前用户具有ROLE_sale这个角色才访问下面的方法
@Secured({"ROLE_sale"})
@GetMapping("update")
public String update() {
return "update";
}
@PreAuthorize("hasAnyAuthority('admins')")
在启动类上加上@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)//开启注解配置权限
//这个注解表示当前用户有这个权限才能访问下面的方法
@PreAuthorize("hasAnyAuthority('admins')")
@GetMapping("upup")
public String upup() {
return "upup";
}
以上两个注解其实作用差不多,和配置类里的那几个类似,是否需要ROLE_前缀的区别
@PostAuthorize("hasAnyAuthority('admins')")
在启动类上加上@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)//开启注解配置权限
//这个注解是先执行方法再验证权限(感觉用处不大)
@PostAuthorize("hasAnyAuthority('admins')")
@GetMapping("xxxx")
public String xxxx() {
System.out.println("xxxxxxxxxxxxxxx");
return "xxxx";
}
@PostFilter对返回的数据进行过滤
@PreFilter对前端传入的数据进行过滤
具体使用时再百度
***********************************************************************************************************
注销用户退出
package com.xu.securitydemo1.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 SecurityConfigByself extends WebSecurityConfigurerAdapter {
//注入userdetailsservice 实现类
@Autowired
private UserDetailsService userDetailsService;
//继承这个类,需要重写父类的方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
//PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
//自定义登录页面
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //自定义登录页面
.loginPage("/login.html") //自定义页面地址
.loginProcessingUrl("/user/login") //登录提交表单之后访问的路径进行UserDetailsService的验证
.defaultSuccessUrl("/success.html").permitAll() //登录成功跳转到的路径
.and().authorizeRequests()
.antMatchers("/", "/test/hello", "/user/login").permitAll() //设置哪些路径不需要登录认证可以直接访问
//表示当前登录的用户只有admins权限的才能访问/test/index
//1.hasAuthority()方法只能写一个权限
//.antMatchers("/test/index").hasAuthority("admins")
//2.hasAnyAuthority()方法有任一权限都可以访问
//.antMatchers("/test/index").hasAnyAuthority("admins,manager")
//3.hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale
//.antMatchers("/test/index").hasRole("sale")
//4.hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_
.antMatchers("/test/index").hasAnyRole("sale")
.anyRequest().authenticated()
.and().csrf().disable();//关闭csrf防护
//配置没有权限跳转的页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
//退出跳转到其他页面 .logoutUrl("/logout")是点击退出的超链接地址 .logoutSuccessUrl("/test/hello")是退出成功后跳转的页面
http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll();
}
}
<body>
登录成功
<a href="/logout">退出</a>
</body>
**************************************************************************************************************
实现自动登录
流程:
通过这个实现类来操作数据库
配置类
package com.xu.securitydemo1.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; import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import javax.sql.DataSource; //第三种方式设置用户名密码,自定义实现类 @Configuration public class SecurityConfigByself extends WebSecurityConfigurerAdapter { //注入userdetailsservice 实现类 @Autowired private UserDetailsService userDetailsService; //注入数据源 @Autowired private DataSource dataSource; //PersistentTokenRepository这个是相当于mapper,里面定义了操作数据库的方法 //JdbcTokenRepositoryImpl是继承PersistentTokenRepository这个接口的实现类 //JdbcTokenRepositoryImpl里有对数据库操作的具体内容 //@Bean将这个对象交给spring管理 @Bean public PersistentTokenRepository persistentTokenRepository() { //new操作数据库的对象 JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl(); //设置数据源来操作具体的数据库 jdbcTokenRepository.setDataSource(dataSource); //这句话的意思是自动创建表(已手动创建就不需要加) //jdbcTokenRepository.setCreateTableOnStartup(true); //返回操作数据库的对象 return jdbcTokenRepository; } //继承这个类,需要重写父类的方法 @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { //设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合 auth.userDetailsService(userDetailsService).passwordEncoder(password()); } //PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类 @Bean PasswordEncoder password() { return new BCryptPasswordEncoder(); } //自定义登录页面 @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() //自定义登录页面 .loginPage("/login.html") //自定义页面地址 .loginProcessingUrl("/user/login") //登录提交表单之后访问的路径进行UserDetailsService的验证 .defaultSuccessUrl("/success.html").permitAll() //登录成功跳转到的路径 .and().authorizeRequests() .antMatchers("/", "/test/hello", "/user/login").permitAll() //设置哪些路径不需要登录认证可以直接访问 //表示当前登录的用户只有admins权限的才能访问/test/index //1.hasAuthority()方法只能写一个权限 //.antMatchers("/test/index").hasAuthority("admins") //2.hasAnyAuthority()方法有任一权限都可以访问 //.antMatchers("/test/index").hasAnyAuthority("admins,manager") //3.hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale //.antMatchers("/test/index").hasRole("sale") //4.hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_ .antMatchers("/test/index").hasAnyRole("sale") .anyRequest().authenticated() //设置操作数据库的对象persistentTokenRepository(),就是在前面定义的 .and().rememberMe().tokenRepository(persistentTokenRepository()) //设置有效时长,秒为单位 .tokenValiditySeconds(60) //用userDetailsService的底层去操作数据库 .userDetailsService(userDetailsService) .and().csrf().disable();//关闭csrf防护 //配置没有权限跳转的页面 http.exceptionHandling().accessDeniedPage("/unauth.html"); //退出跳转到其他页面 .logoutUrl("/logout")是点击退出的超链接地址 .logoutSuccessUrl("/test/hello")是退出成功后跳转的页面 http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll(); } }
第一步创建数据库表:
CREATE TABLE `persistent_logins`(
`username` VARCHAR(64) NOT NULL,
`series` VARCHAR(64) NOT NULL,
`token` VARCHAR(64) NOT NULL,
`last_used` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`series`)
)ENGINE = INNODB DEFAULT CHARSET=utf8;
第二步配置类里注入数据源,配置操作数据库的对象
//注入数据源 @Autowired private DataSource dataSource; //PersistentTokenRepository这个是相当于mapper,里面定义了操作数据库的方法 //JdbcTokenRepositoryImpl是继承PersistentTokenRepository这个接口的实现类 //JdbcTokenRepositoryImpl里有对数据库操作的具体内容 //@Bean将这个对象交给spring管理 @Bean public PersistentTokenRepository persistentTokenRepository() { //new操作数据库的对象 JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl(); //设置数据源来操作具体的数据库 jdbcTokenRepository.setDataSource(dataSource); //这句话的意思是自动创建表(已手动创建就不需要加) //jdbcTokenRepository.setCreateTableOnStartup(true); //返回操作数据库的对象 return jdbcTokenRepository; }
第三步配置类配置自动登录
//设置操作数据库的对象persistentTokenRepository(),就是在前面定义的 .and().rememberMe().tokenRepository(persistentTokenRepository()) //设置有效时长,秒为单位 .tokenValiditySeconds(60) //用userDetailsService的底层去操作数据库 .userDetailsService(userDetailsService)
第四步前端设置一个复选框来自动登录
<form action="/user/login" method="post"> 用户名:<input type="text" name="username"/> <br/> 密码:<input type="password" name="password"/> <br/> <!-- 必须要叫remember-me,因为框架设置好的只会找这个名字--> <input type="checkbox" name="remember-me">自动登录 <br/> <input type="submit" value="login"/> </form>
****************************************************************************************************
CSRF跨站请求伪造
不开启这个csrf会造成同一个浏览器打开多个页面,其他页面也能得到你网站的信息,csrf攻击(实际上是借助浏览器对认证过的网站假装是本人对服务器发送请求)
从springsecurity4.0开始默认开启了csrf保护,这个不对get请求进行防护,只对put,post,delete防护
而我在之前测试的时候关闭了这个防护。
.and().csrf().disable();//关闭csrf防护
需要引入thymeleaf模板引擎
<!-- 引入Thymeleaf添加对springsecurity的标签支持--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency>
在前端登录页加上(必须写在templates下,因为是thymeleaf)
<html lang="en" xmlns:th=" http://www.thymeleaf.org">添加th支持
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
*********************************************************************************************************
微服务权限部分
单点登录