文章目录
1、方案一,只导入依赖不配置
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
这个方案,依赖导入之后SpringBoot项目会自启动,生成默认配置。
规则
- 拦截所有请求
- 内置一个默认的登录界面
- 账号为:user,密码:命令行输出的一串数字(每次启动生成的都不一样)
看图
2、方案二,配置文件直接更改账号,密码,写配置
spring.security.user.name=ljj
spring.security.user.password=1111
3、方案三,写一个配置类
比如,具体意思写在注释了
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 表单登录
.and()
.authorizeRequests() // 认证配置
.anyRequest() // 任何请求
.authenticated(); // 都需要身份验证
//.permitAll(); // 都放行
}
4、方案四,写一个配置类,同时能设置登录的账号和密码
写一个自定义用户实现类
package com.atguigu.csrfsecurity.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.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 javax.annotation.Resource;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public BCryptPasswordEncoder newBCryptPasswordEncoder(){
return new BCryptPasswordEncoder(); //没有这个会报错
}
//实现用户身份认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode("1111");
auth.inMemoryAuthentication().withUser("ljj").password(password).roles("admin");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 表单登录
.and()
.authorizeRequests() // 认证配置
.anyRequest() // 任何请求
.authenticated(); // 都需要身份验证
}
}
5、方案五,写一个服务类(设置账号密码)+配置类
写一个服务类UserDetailsServiceImpl
package com.atguigu.csrfsecurity.service;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
List<SimpleGrantedAuthority> list = new ArrayList<>();
list.add(new SimpleGrantedAuthority("role"));
UserDetails userDetails = new User("ljj", new BCryptPasswordEncoder().encode("123")
, list);
return userDetails;
}
}
在配置类中注入服务类
package com.atguigu.csrfsecurity.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.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 javax.annotation.Resource;
import javax.sql.DataSource;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
UserDetailsService userDetailsService; //实际是注入上面的服务类UserDetailsServiceImpl
//实现用户身份认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
auth.userDetailsService(userDetailsService).passwordEncoder(encoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//配置url的访问权限
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/**update**").permitAll()
.antMatchers("/login/**").permitAll()
.anyRequest().authenticated();
}
}
6、方案六、实现自定义登录页面设置
把下面的代码写入配置类,这些就是自定义设置登录页面
//使用自定义的登录窗口
http.formLogin()
.loginPage("/userLogin").permitAll() //认证之前跳转的页面,登录访问路径默认和登录页面路径一致了
.loginProcessingUrl("/ceshi") //设置登录访问路径
.usernameParameter("username").passwordParameter("password") //设置登录访问路径需要的参数
.defaultSuccessUrl("/test") //成功之后的跳转,重定向
.failureUrl("/userLogin?error"); //登录失败之后的跳转,转发
我写的完整配置类
package com.atguigu.csrfsecurity.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.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 javax.annotation.Resource;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 表单登录
.and()
.authorizeRequests() // 认证配置
.anyRequest() // 任何请求
.authenticated(); // 都需要身份验证
//使用自定义的登录窗口
http.formLogin()
.loginPage("/userLogin").permitAll() //认证之前跳转的页面,登录访问路径默认和登录页面路径一致了
.loginProcessingUrl("/ceshi") //设置登录访问路径
.usernameParameter("username").passwordParameter("password") //设置登录访问路径需要的参数
.defaultSuccessUrl("/test") //成功之后的跳转,重定向
.failureUrl("/userLogin?error"); //登录失败之后的跳转,转发
//.failureForwardUrl("/test01");
}
}
7、实现从数据库中读取账号密码
7.1 配置类
package com.atguigu.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 SecurityConfigTest extends WebSecurityConfigurerAdapter {
//注入用户数据源
@Autowired
private UserDetailsService userDetailsService;
//注入数据源
@Autowired
private DataSource dataSource;
//配置数据库对象注入
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
//配置用户注入
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
//拦截配置
@Override
protected void configure(HttpSecurity http) throws Exception {
//退出
http.logout().logoutUrl("/logout").
logoutSuccessUrl("/test/hello").permitAll();
//配置没有权限访问跳转自定义页面
//http.exceptionHandling().accessDeniedPage("/unauth.html");
http.formLogin() //自定义自己编写的登录页面
//.loginPage("/on.html") //登录页面设置
.loginPage("/login") //登录页面设置
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/success.html").permitAll() //登录成功之后,跳转路径
//.failureUrl("/unauth.html") //登录失败之后,跳转路径
.failureUrl("/login?error")
.and().authorizeRequests()
.antMatchers("/","/test/hello","/user/login","/unauth.html").permitAll() //设置哪些路径可以直接访问,不需要认证
//当前登录用户,只有具有admins权限才可以访问这个路径
//1 hasAuthority方法
// .antMatchers("/test/index").hasAuthority("admins")
//2 hasAnyAuthority方法
// .antMatchers("/test/index").hasAnyAuthority("admins,manager")
//3 hasRole方法 (实际角色为ROLE_sale,这里配置的sale都都会默认加上前缀ROLE_)
.antMatchers("/test/index").hasRole("sale")
.anyRequest().authenticated()
.and().rememberMe().tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(60)//设置有效时长,单位秒
.userDetailsService(userDetailsService);
// .and().csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
// .and().csrf().disable(); //关闭csrf防护
}
}
7.2 用户服务类用数据库验证
package com.atguigu.securitydemo1.service;
import com.atguigu.securitydemo1.entity.Users;
import com.atguigu.securitydemo1.mapper.UsersMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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;
//指定bean的名字
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UsersMapper usersMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//调用usersMapper方法,根据用户名查询数据库
QueryWrapper<Users> wrapper = new QueryWrapper();
// where username=?
wrapper.eq("username",username);
Users users = usersMapper.selectOne(wrapper);
//判断
if(users == null) {//数据库没有用户名,认证失败
throw new UsernameNotFoundException("用户名不存在!");
}
List<GrantedAuthority> auths =
AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_sale");
//从查询数据库返回users对象,得到用户名和密码,返回
return new User(users.getUsername(),
new BCryptPasswordEncoder().encode(users.getPassword()),auths);
}
}
7.3 配置类中的DataSource(系统自带的
连接数据库的的配置写在yml文件
#mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=1111
这个类会自动读取yml文件中的数据,自动注入
8、Spring EL表达式
Spring Security允许我们在定义URL访问或方法访问所应有的权限时使用Spring EL表达式,在定义所需的访问权限时如果对应的表达式返回结果为true则表示拥有对应的权限,反之则无。Spring Security可用表达式对象的基类是SecurityExpressionRoot,其为我们提供了如下在使用Spring EL表达式对URL或方法进行权限控制时通用的内置表达式。
表达式 | 描述 |
---|---|
hasRole([role]) | 当前用户是否拥有指定角色。 |
hasAnyRole([role1,role2]) | 多个角色是一个以逗号进行分隔的字符串。如果当前用户拥有指定角色中的任意一个则返回true。 |
hasAuthority([auth]) | 等同于hasRole |
hasAnyAuthority([auth1,auth2]) | 等同于hasAnyRole |
Principle | 代表当前用户的principle对象 |
authentication | 直接从SecurityContext获取的当前Authentication对象 |
permitAll | 总是返回true,表示允许所有的 |
denyAll | 总是返回false,表示拒绝所有的 |
isAnonymous() | 当前用户是否是一个匿名用户 |
isRememberMe() | 表示当前用户是否是通过Remember-Me自动登录的 |
isAuthenticated() | 表示当前用户是否已经登录认证成功了。 |
isFullyAuthenticated() | 如果当前用户既不是一个匿名用户,同时又不是通过Remember-Me自动登录的,则返回true。 |