java configuration方式
- 上面是以xml文件的方式配置,接下来介绍以自定义java类的方式来配置spring security
- 可先在719行:自定义过滤器一节了解认证流程。
1. 注册DelegatingFilterProxy
package com.study.config;
import org.springframework.security.web.context.*;
public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { WebSecurityConfig.class };
}
}
-
继承该类相当于在web.xml中:
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter>
-
重写getRootConfigClasses()相当于把下一步Spring Security的配置加载到程序中。
2. Spring Security安全配置
package com.study.config;
import javax.annotation.Resource;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import com.study.security.MyFilterSecurityInterceptor;
@Configuration
@EnableWebSecurity //启用web安全功能
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// @Resource
// private DataSource dataSource;
//配置自定义的用户服务(即选择用户信息的查询方式是从用户库或数据库,怎么查询)
@Resource(name="myUserDetailService")
private UserDetailsService myUserDetailService;
//第3点:自定义用户验证
@Resource
private AuthenticationProvider myAuthenticationProvider;
//自定义认证成功处理器
@Resource
private AuthenticationSuccessHandler myAuthenticationSuccessHandler;
//第4点:自定义拦截器(自定义权限验证,而不是拦截规则)
@Resource
private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
/**
* 密码加密
*/
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/**
* 自定义认证过程
*/
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
/* 不重写的话默认为
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER"); //默认准备了一个用户
*/
//方式一:内存用户存储
/*
auth.inMemoryAuthentication()
.withUser("user1").password("123456").roles("USER").and()
.withUser("admin").password("admin").roles("USER","ADMIN");
*/
//
//方式二:数据库表认证
/*
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username,password,enable from t_user where username=?")
.authoritiesByUsernameQuery("select username,rolename from t_role where username=?");
*/
//方式三:自定义数据库
auth.userDetailsService(myUserDetailService)
.passwordEncoder(new Md5PasswordEncoder());
//加后MyAuthenticationProvider里比对密码时能把表单的明文和数据库的密文对应
//自定义用户验证
auth.authenticationProvider(myAuthenticationProvider);
}
// 暴露默认的authenticationManager
// @Override
// public AuthenticationManager authenticationManagerBean() throws Exception {
// return super.authenticationManagerBean();
// }
/**
* 配置Spring Security的Filter链
*/
@Override
public void configure(WebSecurity web)throws Exception {
// 设置不拦截规则
web.ignoring().antMatchers("/css/**","/js/**","/img/**","/font-awesome/**");
}
/**
* 配置如何通过拦截器保护请求:配置了自定义的过滤器、自定义登录登出页面
* 前端请求的时候先经过这里检测请求是否需要验证或权限,不需要的话直接把请求分发给controller去处理,需要就认证过了再分发
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(myFilterSecurityInterceptor,
FilterSecurityInterceptor.class)//在正确的位置添加我们自定义的过滤器
.authorizeRequests() //需要权限,权限符合与否由上面过滤器检查
.antMatchers("/admin/**").hasRole("ADMIN") //以admin开头的url需要admin权限
.antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
.anyRequest().authenticated() //不与以上匹配的所有请求只需要登录验证
// .and().formLogin().and() //and相当于节点结束
// .httpBasic();
// 自定义登录页面:permitAll,允许all用户访问login页面
//未登录前访问受保护资源被转回login
.and()
/*直接/jsp/login的话会分配给controller去处理,则需要写controller映射到登录页;请求login.jsp报404
有后缀则直接请求资源,那么url=/login还是由controller处理;
那么最好是加后缀,才不用再走controller*/
.formLogin().loginPage("/jsp/login.jsp")
.failureUrl("/jsp/login.jsp?error=1")
//表单提交地址,4.x默认为/login;无需认证,但是请求方式必须post
.loginProcessingUrl("/spring_security_check")
.usernameParameter("username")
.passwordParameter("password")
.successHandler(myAuthenticationSuccessHandler) //自定义认证成功处理器
//.failureHandler(myAuthenticationFailureHandler)
.permitAll()
//这里也是,要么配资源路径,要么配有controller处理的url
.defaultSuccessU