1.定义
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
https://springcloud.cc/spring-security-zhcn.html 中文版参考手册
2.基本原理:一组过滤器链

UsernamePasswordAuthenticationFilter:用户认证
ExceptionTranslation:异常处理
FilterSecurityInterceptor:最终确认是否能登录的拦截器
备注:在没有验证的情况下,登录后会到默认的验证页面,默认会拦截所有页面,待验证成功后会转到相应的页面
3.依赖
<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>
4.Api简要说明
authorizeRequests():请求授权
formLogin():表单登录(表单登录含两部分一个是认证一个是授权)
anyRequest():任何请求
authenticated():身份认证
httpBasic():httpBasic认证方式
loginPage():指定登录时的认证页面,这里有一个坑死循环需要注意。
antMatchers():匹配
permitAll():不需要身份认证
5.使用数据库验证登录方式
@Configuration
@ComponentScan("springsecurity.demo")
@MapperScan("springsecurity.demo.Mapper")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()//表单登录
.and()
.authorizeRequests()//权限认证
.anyRequest()//任何请求
.authenticated()//需要认证
;
}
}
@Component
public class MyUserDetailsService implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Autowired
PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) {
//查询表
springsecurity.demo.domain.User userByName = userMapper.getUserByName(username);
//加密
String encode = passwordEncoder.encode(userByName.getPassword().toString());//应该是在放入数据库的时候加密,这里直接直接取出
//将查询的结果放入user中,
// AuthorityUtils.commaSeparatedStringToAuthorityList("admin")表示角色admin(拥有的权限)
return new User(username,encode , AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));//需要采用加密方式否者出现{id}为null
}
}
@Configuration
public class SecurityBeanConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource getdaDataSource(){
return new DruidDataSource();
}
@Bean
public PasswordEncoder getPasswordEncoder(){
return new BCryptPasswordEncoder();//springsecurity 内置的加密器,建议使用
}
}
@RestController
public class UserController {
@GetMapping("/hello")
public String testLogin(){
return "helloworld security";
}
}
自定义加密方式
需要实现PasswordEncoder
重写方法
encode:对密码进行加密
matches(CharSequence var1, String var2):var1原密码,var2传过来的密码
User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities)
enabled:是否可用
accountNonExpired:账户是否过期
credentialsNonExpired:密码是否过期
accountNonLocked:是否被冻结
6.自定义登录页面
6.1使用默认的自定义方式配置
@Configuration
@ComponentScan("springsecurity.demo")
@MapperScan("springsecurity.demo.Mapper")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/logintest.html") //登录页面定义
.loginProcessingUrl("/authentication/logintest")//默认处理的是login post
.and()
.authorizeRequests()
.antMatchers("/logintest.html")
.permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().disable()//跨站域请求伪造关闭,注意不关闭在Chrome中没反应
;
}
}
6.2使用自定义配置登录页面
@Configuration
@ComponentScan("springsecurity.demo")
@MapperScan("springsecurity.demo.Mapper")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MySecurityProperties mySecurityProperties;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/logintest")
.loginProcessingUrl("/authentication/logintest")
.and()
.authorizeRequests()
.antMatchers("/logintest",mySecurityProperties.getLogin())
.permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().disable()
;
}
}
@RestController
public class UserController {
HttpSessionRequestCache cache= new HttpSessionRequestCache();
DefaultRedirectStrategy defaultRedirectStrategy = new DefaultRedirectStrategy();//重定向页面
@Autowired
MySecurityProperties securityProperties;
@GetMapping("/logintest")
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Message testAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException {
SavedRequest savedRequest = cache.getRequest(request, response);
if(savedRequest!=null){
String redirectUrl = savedRequest.getRedirectUrl();//获取请求地址
if(StringUtils.endsWithIgnoreCase(redirectUrl, ".html")){
defaultRedirectStrategy.sendRedirect(request, response, securityProperties.getLogin());
}
}
return new Message("请先登录");
}
}
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class Message implements Serializable {
private Object mesaage;
}
<body>
<h2 style="color: red">简单的登录页面login</h2>
<form action="/authentication/logintest" method="post">
<table>
<tr>
<td>账号:</td>
<td ><input type="text" name="username"/></td>
</tr>
<tr>
<td>密码:</td>
<td> <input type="password" name="password"/></td>
</tr>
<tr>
<td colspan="2" style="text-align: right"><input type="submit" value="提交" /></td>
</tr>
</table>
</form>
</body>
</html>
@ConfigurationProperties("spring.security")
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
@Component
public class MySecurityProperties {
private String login="/logintest.html";
}
7.自定义成功登陆的返回值
@Configuration
@ComponentScan("springsecurity.demo")
@MapperScan("springsecurity.demo.Mapper")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MySecurityProperties mySecurityProperties;
@Autowired
MyUserDetails myUserDetails;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/logintest")
.loginProcessingUrl("/authentication/logintest")
.successHandler(myUserDetails)
.and()
.authorizeRequests()
.antMatchers("/logintest",mySecurityProperties.getLogin())
.permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().disable()
;
}
}
@Component
public class MyUserDetails implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(new ObjectMapper().writeValueAsString(authentication));
}
}
失败类似
实现AuthenticationFailureHandler实现onAuthenticationFailure方法
.failureHandler(AuthenticationFailureHandler xxx)
8.图片验证