引入SpringSecurity模块
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
加入这个依赖后表示所有的接口都是被保护的状态,访问的时候被Security拦截。
在浏览器输入该请求路径,会自重定向到Spring Security的登录页。默认的用户名是user,密码请去IDEA的Consolse去找项目每次启动时随机生成的字符串:
Using generated security password: 5a38aea2-81d0-485d-bf5c-12c73b0aad27
(复制passwor后的内容即可访问)
同时也支持在数据库配置用户名和密码(正式项目一般处理方式)或在配置文件配置用户名密码,本文使用的是yml配置,properties同理,如果不知道如何配置,请自行百度。配置后在Console中便不自动生成password
spring:
security:
user:
name: Ltx
password: 123456
# roles可不配置
roles: admin
配置HTTP拦截规则
配置接口放行规则
SecurityConfig.class
/**
* @author Liutx
* @date 2020/12/13 11:53
* @Description
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 实际就是为了告诉Spring我的密码不用加密
*/
@Bean
PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
/**
* configure有三个重写的方法,本方法是基于内存的配置用户角色
* 在Spring 5.0后需要对密码进行加密
*/
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root").password("123456").roles("admin")
.and()
.withUser("Ltx").password("123456").roles("user");
}
/**
* 配置HTTP请求规则
* 什么请求路径需要什么权限才能访问,
* 登录接口,都可访问
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O object) {
object.setAccessDecisionManager(customUrlDecisionManager);
object.setSecurityMetadataSource(customFilterInvocationSecurityMetadataSource);
return object;
}
})
.and()
.logout()
.logoutSuccessHandler((req, resp, authentication) -> {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write(new ObjectMapper().writeValueAsString(RespBean.ok("注销成功!")));
out.flush();
out.close();
}
)
.permitAll()
.and()
.csrf().disable().exceptionHandling()
//没有认证时,在这里处理结果,不要重定向
.authenticationEntryPoint((req, resp, authException) -> {
resp.setContentType("application/json;charset=utf-8");
resp.setStatus(401);
PrintWriter out = resp.getWriter();
RespBean respBean = RespBean.error("访问失败!");
if (authException instanceof InsufficientAuthenticationException) {
respBean.setMsg("请求失败,请联系管理员!");
}
out.write(new ObjectMapper().writeValueAsString(respBean));
out.flush();
out.close();
}
);
http.addFilterAt(new ConcurrentSessionFilter(sessionRegistry(), event -> {
HttpServletResponse resp = event.getResponse();
resp.setContentType("application/json;charset=utf-8");
resp.setStatus(401);
PrintWriter out = resp.getWriter();
out.write(new ObjectMapper().writeValueAsString(RespBean.error("您已在另一台设备登录,本次登录已下线!")));
out.flush();
out.close();
}), ConcurrentSessionFilter.class);
http.addFilterAt(loginFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
使用postman测试,所以关闭CSRF攻击,正式环境请开启 记得要删掉super.configure(http); 不然会报错IllegalStateException: Can't configure anyRequest after itself ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然。它使用JsonParser和JsonGenerator的实例实现JSON实际的读/写。
表单登录测试
使用post请求构造表单登录,SpringSecurity已做密码脱敏,权限中默认使用"ROLE_"为前缀。
表单登出测试
登出配置如上代码,构造get请求即可。
使用数据库的方式做登录认证
一、引入数据库驱动、orm框架(MyBatis-Plus)
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 引入阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.3</version>
</dependency>
<!--MyBatis-Plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>8.0.22</version>
</dependency>