一 . springsecurity简介
springsecurity是一个安全框架,它能提供登录验证,权限认证的功能
二. springsecurity的使用
这篇写的挺好的,我的要是看不懂,可以看这个
我们最关心的大概都是是如何用springsecurity,有想看背后原理的小伙伴可以自行去度娘,本博文内容包括如何添加保护路径及如何设置登录验证及权限验证!;
- 首先在pom文件导入SpringSecurity依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 之后创建一个配置类,继承WebSecurityConfigurerAdapter这个类,其中根据需求可以重写WebSecurityConfigurerAdapter中多个configure()方法
代码如下
@Configuration
public class MyWebSecurityconfigure extends WebSecurityConfigurerAdapter {
}
添加保护路径
protected configure(HttpSecurity)
configure(HttpSecurity)方法定义了哪些URL路径应该被保护,哪些不应该,我将在下边举出常用的例子,你们看过后应该明白的更快点!
插播几个常用api的用法;
- permitAll()
- 若跟在
antMatchers()
后使用,代表所有路径均可访问
- 若跟在
- anyRequest()
- 若跟在
permitAll()
后使用,代表所有路径均不可访问,除啦permitAll()
修饰过的路径,注意若使用此api,则所有不需要保护的路径都呆加上permitAll()修饰;
- 若跟在
登录验证
springsecurity关于登陆验证的实现我晓得的有两种,第一种内存验证登录,第二种jdbc
内存验证登录
只需要在配置类里加上这段便可以完成一个内存验证登录,注意springsecurity5后强制要求进行密码加密操作
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//此路径需要admin权限用户才可访问
.antMatchers("/adminshow.html").hasRole("admin").
//任何路径都是登录后即可访问;
anyRequest().authenticated().and().
//设置登陆页,默认被拦截后都跳回登陆页
formLogin().loginPage("/login.html").usernameParameter("username") .passwordParameter("password").
//设置表单提交路径
loginProcessingUrl("/login").permitAll().
//成功后如何处理
successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("success");
out.flush();
} //注意,不需要csrf防护时一定要禁用喽,否则一样拦截你;
}).and().csrf().disable();
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().
//在内存中创建啦用户名为“lisi”
withUser("lisi").
//用户密码为“123”,此处必须填加密后的值
password(new BCryptPasswordEncoder().encode("123")).
//角色权限为“user”的这么一个用户
roles("user");
}
//Spring Security 中提供了BCryptPasswordEncoder 密码编码工具,可以非常方便的实现密码的加密加盐,相同明文加密出来的结果总是不同
//将Spring Security 中提供的BCryptPasswordEncoder加密类注入到spring容器中;
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
JDBC登录验证
根据下述操作来;
- user对象实现UserDetails接口;
//UserDetails接口
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
/**
* 账号是否失效,返回false账号失效,不可用。
*/
boolean isAccountNonExpired();
/**
* 账号是否被锁,返回false,账号被锁,不可用
*/
boolean isAccountNonLocked();
/**
* 账号认证是否过期,返回false,过期,不可用
*/
boolean isCredentialsNonExpired();
/**
* 账号是否可用。返回false不可用
*/
boolean isEnabled();
}
public class User implements UserDetails {
Long id;
String username;
String password;
List<Role> roles;
public User() {
}
public User(Long id, String username, String password, List<Role> roles) {
this.id = id;
this.username = username;
this.password = password;
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return roles;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
- Role类实现GrantedAuthority这个接口
public class Role implements GrantedAuthority {
private Long id;
private String name;
public Role() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Role(Long id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getAuthority() {
return this.name;
}
}
- service层实现UserDetailsService这个接口并重写其中的loadUserByUsername方法;
@Service
public class UserService implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Autowired
RoleMapper roleMapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userMapper.loadUserByUsername(s);
List<Role> rolesbyname = roleMapper.rolesbyname(s);
/*注意此处关于角色权限名字必须是ROLE_*的形式,否则不认你,
所以我在此处又重新设置啦下角色权限的名字*/
for (Role role : rolesbyname) {
role.setName("ROLE_"+role.getName());
}
//此处必须返回新建的对象;
return user == null ? null : new User(user.getId(), s, new BCryptPasswordEncoder().encode(user.getPassword()), rolesbyname);
}
}
- 最后在自定义安全配置类中重写configure(AuthenticationManagerBuilder auth)方法,将你的service层 传入进去;
@Configuration
public class MyWebsecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
/*
springsecurity通过loginProcessingUrl这个方法添加登录验证路径,loginPage添加登陆页面,
不添加的默认使用springsecurity自带的登录页面,usernameParameter获取用户
名,passwordParameter获取登录表单的密码
*/
http.authorizeRequests().antMatchers("/adminshow.html").hasRole("admin").anyRequest().authenticated().and().formLogin().loginPage("/login.html").usernameParameter("username")
.passwordParameter("password").loginProcessingUrl("/login").permitAll().successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("success");
out.flush();
}
}).and() //不用csrf时就关闭它;
.csrf().disable();
}
//将你的userservice交给springsecurity去处理
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
//重要,这个不能丢,加密用的!
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
上述一系列操作完成,springsecurity就可以代替你完成登录及权限认证的操作!
总结: