我们一般用到的主流安全框架有两种:
Shiro
Spring Security
相对于 Shiro,在 SSM/SSH 中整合 Spring Security 都是比较麻烦的操作,所以,Spring Security 虽然功能比 Shiro 强大,但是使用反而没有 Shiro 多(Shiro 虽然功能没有 Spring Security 多,但是对于大部分项目而言,Shiro 也够用了)。
本文主要讲解spring security
实战:
(1)创建web项目,引入security和web依赖即可,pom.xml配置如下:
<dependencies>
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
(2)此时创建测试controller。
@RestController
public class SecurityController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
@GetMapping("/login")
public String login() {
return "login";
}
}
(3)此时访问/hello,security会提示登录,默认的用户是user 密码为123。
(4)当然,我们可以手动设置登录的账户和密码。有两种方式:
第一种方式: application.properies文件中设置
spring.security.user.name=javaboy
spring.security.user.password=123
第二种方式:创建配置类继承自WebSecurityConfigurerAdapter。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//手动设置两个用户 一个权限为admin 一个权限为user
auth.inMemoryAuthentication()
.withUser("javaboy").roles("admin").password("1234")
.and()
.withUser("fyf").roles("user").password("123");
}
//注入这个bean是因为spring 5.0以后设置用户密码必须密文进行设置
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
}
注意: 如果 application.properies和代码里设置相同用户名的密码,代码中设置优先级会更高。
(5)此时继续访问/hello ,输入正确的用户名及其密码即可访问,此外我们还可以在继承了WebSecurityConfigurerAdapter的配置类中进行其他配置。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() //开启登录配置
.antMatchers("/hello").hasRole("admin") //表示访问 /hello 这个接口,需要具备 admin 这个角色
.anyRequest().authenticated() //表示剩余的其他接口,登录之后就能访问
.and()
.formLogin() //登录接口可以进行表单提交
.loginProcessingUrl("/doLogin") //登录处理接口 方便postman进行测试
.usernameParameter("uname") //登录表单的username可以自定义
.passwordParameter("passwd")
.successHandler(new AuthenticationSuccessHandler() {
//登录成功的回调
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter writer = resp.getWriter();
Map<String,Object> map = new HashMap<>();
map.put("status",200);
map.put("msg",authentication.getPrincipal());
writer.write(new ObjectMapper().writeValueAsString(map));
writer.flush();
writer.close();
}
})
.failureHandler(new AuthenticationFailureHandler() {
//登录失败的回调
@Override
public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException e) throws IOException, ServletException {
//对异常进行判断并返回给前
}
})
.permitAll() //和表单登录相关的接口统统都直接通过
.and()
.logout() //注销登录
.logoutUrl("/logout") //注销处理接口 方便postman进行测试
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse
resp, Authentication authentication) throws IOException, ServletException {
//注销成功的回调
resp.setContentType("application/json;charset=utf-8");
PrintWriter writer = resp.getWriter();
Map<String,Object> map = new HashMap<>();
map.put("status",200);
map.put("msg",authentication.getPrincipal());
writer.write(new ObjectMapper().writeValueAsString(map));
writer.flush();
writer.close();
}
})
.and()
//关闭 防止csrf攻击,否则postman无法访问
.csrf().disable();
}
(6)测试,登录fyf用户,fyf用户的权限是user
访问/hello接口,被禁止,因为只有具有admin权限的用户才能访问。
此时将fyf用户注销
登录javaboy用户,访问/hello接口,访问成功。
看到这,恭喜小伙伴们 基本spring security也算入了个门!!!