概述
Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于 Spring 的应用程序的事实上的标准
Spring Security 是一个专注于为 Java 应用程序提供身份验证和授权的框架。与所有 Spring 项目一样,Spring Security 的真正强大之处在于它可以轻松扩展以满足自定义要求
特征
- 对身份验证和授权的全面且可扩展的支持
- 防止会话固定、点击劫持、跨站点请求伪造等攻击
- Servlet API 集成
- 与 Spring Web MVC 的可选集成
实现
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
测试
@RestController
public class DemoController {
@RequestMapping("/hello")
public String hello(){
return "hello world";
}
}
然后我们启动项目,按照我们正常的理解,直接访问
localhost:8080/hello
会返回hello world 。但结果却是重定向到了/login 。下面的界面是Spring security 自带的
其实上面可以看到,Spring security 已经起作用了,没有登录不能访问 /hello 接口
默认的用户名为 user
密码在我们项目启动时控制台有打印,每次都会不一样,随机生成的
可以看到,在登录之后,我们在请求 /hello 会直接返回hello world , 那是不是只要登录一次,后面就可以一直访问呢?当然不是的,登录成功之后,会将信息保存在session 中,再登录的时候,就会通过session 校验,这样就可以访问到了,当session过期获取我们手动清理掉后,就需要重新登录了
application.yml文件中的配置
spring:
security:
user:
name: feiniu
password: 123456
roles: admin
分别是设置用户名,密码,角色。我们这里暂时只用了用户认证,所以角色设不设置无所谓
可以看到依然能够登陆成功,但是实际开发当中,我们并不使用这种方法进行配置
配置类进行配置
@Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
// 指定加密方式
.passwordEncoder(passwordEncoder())
.withUser("feiniu").password(passwordEncoder().encode("123456")).roles("admin")
.and()
.withUser("test").password(passwordEncoder().encode("123456")).roles("USER");
}
@Bean
public PasswordEncoder passwordEncoder() {
// BCryptPasswordEncoder:Spring Security 提供的加密工具
return new BCryptPasswordEncoder();
}
}
这里我们重写了configure(AuthenticationManagerBuilder auth) 方法,就是将定义的用户配置到内存中。这里有一个问题需要说明一下,就是这里配置的话,密码需要用BCryptPasswordEncoder 加密。如果不加密的话,项目编译启动不会报错,但是登陆的时候就会提示账号密码错误 如果我们在这配置了,那我们在application.peoperties 中配置的就会失效
上述的这两种都不常用,只是为了小编初步学习,所以列举了出来,我们在实际项目中根本不会在项目中写死用户信息的,基本上都是存在数据库中,所以下面我们就开始讲解我们最常用的模式
从数据库进行用户认证
既然是用到数据库,项目中自然要引入数据的配置,我这里用的是mysql 和mybatis
实体类
@Getter
@Setter
public class RolePO {
private Long id;
private String name;
}
我们在创建 UserEntry ,但是UserEntry 比较特殊,因为我们需要使用Spring security 。所以这里,UserEntry 需要实现 UserDetails
@Setter
@Getter
public class UserPO implements UserDetails {
private Long id;
private String username;
private String password;
private String nickname;
private boolean enabled;
private List<RolePO> roles;
private String email;
private String userface;
private Timestamp regTime;
/**
* 获取角色权限
* @return
*/
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
for (RolePO role : roles) {
authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
}
return authorities;
}
/**
* 获取密码
* @return
*/
@Override
public String getPassword() {
return password;
}
/**
* 获取用户名
* @return
*/
@Override
public String getUsername() {
return username;
}
/**
* 用户账号是否过期
*/
@Override
public boolean isAccountNonExpired() {
return true;
}
/**
* 用户账号是否被锁定
*/
@Override
public boolean isAccountNonLocked() {
return true;
}
/**
* 用户密码是否过期
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}
/**
* 用户是否可用
*/
@Override
public boolean isEnabled() {
return enabled;
}
}
然后写好mapper文件,mapper,dao,service
在service 层我们要注意一点,我们需要实现 UserDetailsService 接口。 我们先创建一个UserService 继承 UserDetailsService。然后创建一个UserServiceImpl 来时实现UserService 从而达到实现UserDetailsService的目的
service
public interface UserService extends UserDetailsService {
}
serviceImpl
@Service
@Slf4j
public class UserServiceImpl implements UserService {
@Autowired
UserMapper userMapper;
@Autowired
RolesMapper rolesMapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
UserPO user = userMapper.loadUserByUsername(s);
if (user == null) {
//避免返回null,这里返回一个不含有任何值的User对象,在后期的密码比对过程中一样会验证失败
return new UserPO();
}
//查询用户的角色信息,并返回存入user中
List<RolePO> roles = rolesMapper.getRolesByUid(user.getId());
user.setRoles(roles);
return user;
}
}
SecurityConfig
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Bean
public PasswordEncoder passwordEncoder() {
// BCryptPasswordEncoder:Spring Security 提供的加密工具
return new BCryptPasswordEncoder();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService)
.passwordEncoder(passwordEncoder());//passwoldEncoder是对密码的加密处理,如果user中密码没有加密,则可以不加此方法。注意加密请使用security自带的加密方式。
}
然后启动项目,访问http://localhost:8080/hello, 就可以使用数据库当中user表和role表当中对应的用户和权限。
注意:下面给大家提供了一些配置项的参考内容,详情参考www.cnblogs.com/crazy-lc/p/…
今天的分享就到这里啦,希望能给你带来帮助!!!