Nuñ*_*ada 9 rest restful-authentication spring-security jwt spring-boot
我有一个SpringBoot 2.0.2.RELEASE Web应用程序,带有这个配置文件:
@Override
protected void configure(HttpSecurity http) throws Exception {
final List<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
if (activeProfiles.contains("dev")) {
http.csrf().disable();
http.headers().frameOptions().disable();
}
http
.authorizeRequests()
.antMatchers(publicMatchers()).permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/bonanza/list")
.failureUrl("/login?error").permitAll()
.and()
.logout().permitAll();
}
Run Code Online (Sandbox Code Playgroud)
我想添加一个基于自定义JWT的安全过滤器,仅用于匹配的Rest控制器/rest/**,所以我将配置修改为此文件,但现在我无法登录到应用程序,因为我有一个HTTP状态401 -擅自
@Override
protected void configure(HttpSecurity http) throws Exception {
final List<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
if (activeProfiles.contains("dev")) {
http.csrf().disable();
http.headers().frameOptions().disable();
}
http
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(publicMatchers()).permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/bonanza/list")
.failureUrl("/login?error").permitAll()
.and()
.logout().permitAll();
// Custom JWT based security filter
JwtAuthorizationTokenFilter authenticationTokenFilter = new JwtAuthorizationTokenFilter(userDetailsService(), jwtTokenUtil, tokenHeader);
http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
Run Code Online (Sandbox Code Playgroud)
和过滤器(从...延伸OncePerRequestFilter)
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
logger.info("processing authentication for '{}'", request.getRequestURL());
if (request.getRequestURI().indexOf("/rest/")==-1) {
chain.doFilter(request, response);
return;
}
final String requestHeader = request.getHeader(this.tokenHeader);
String username = null;
String authToken = null;
if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
authToken = requestHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(authToken);
} catch (IllegalArgumentException e) {
logger.info("an error occured during getting username from token", e);
} catch (ExpiredJwtException e) {
logger.info("the token is expired and not valid anymore", e);
}
} else {
logger.info("couldn't find bearer string, will ignore the header");
}
logger.info("checking authentication for user '{}'", username);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
logger.info("security context was null, so authorizating user");
// It is not compelling necessary to load the use details from the database. You could also store the information
// in the token and read it from it. It's up to you ;)
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
// For simple validation it is completely sufficient to just check the token integrity. You don't have to call
// the database compellingly. Again it's up to you ;)
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
logger.info("authorizated user '{}', setting security context", username);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(request, response);
}
....
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return request.getRequestURI().indexOf("/rest/")==-1;
}
Run Code Online (Sandbox Code Playgroud)
在记录器中,我看到了
("couldn't find bearer string, will ignore the header"
Run Code Online (Sandbox Code Playgroud)
因为我只想在RestContollers中应用JWT过滤器而不是所有这些过滤器,例如LoginController
使用此配置类,我可以访问仅在应用程序中登录的/ rest/URL.
@Profile("web")
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger LOG = LoggerFactory.getLogger(WebSecurityConfig.class);
@Autowired
private UserSecurityService userSecurityService;
@Value("${server.servlet.context-path}")
private String serverContextPath;
/** The encryption SALT. */
private static final String SALT = "fd&lkj§sfs23#$1*(_)nof";
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12, new SecureRandom(SALT.getBytes()));
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Configuration
@Order(1)
public static class ApiSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Value("${jwt.header}")
private String tokenHeader;
@Value("${jwt.route.authentication.path}")
private String authenticationPath;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// we don't need CSRF because our token is invulnerable
.csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// don't create session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(“/rest/**”).permitAll().anyRequest().authenticated()
.antMatchers(“**/rest/**”).permitAll().anyRequest().authenticated();
// Custom JWT based security filter
JwtAuthorizationTokenFilter authenticationTokenFilter = new JwtAuthorizationTokenFilter(userDetailsService(), jwtTokenUtil, tokenHeader);
http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// disable page caching
http.headers().frameOptions().sameOrigin() // required to set for H2 else H2 Console will be blank.
.cacheControl();
}
}
@Configuration
@Order(0)
public static class OtherSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Value("${server.servlet.context-path}")
private String serverContextPath;
@Autowired
private Environment env;
@Override
protected void configure(HttpSecurity http) throws Exception {
final List<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
if (activeProfiles.contains("dev")) {
http.csrf().disable();
http.headers().frameOptions().disable();
}
http.authorizeRequests()
.antMatchers(publicMatchers())
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/bonanza/list")
.failureUrl("/login?error").permitAll()
.and()
.logout()
.permitAll();
}
private String[] publicMatchers() {
/** Public URLs. */
final String[] PUBLIC_MATCHERS = {
"/webjars/**",
serverContextPath + "/css/**",
serverContextPath + "/js/**",
serverContextPath + "/fonts/**",
serverContextPath + "/images/**",
serverContextPath ,
"/",
"/error/**/*",
"/console/**",
ForgotMyPasswordController.FORGOT_PASSWORD_URL_MAPPING,
ForgotMyPasswordController.CHANGE_PASSWORD_PATH,
SignupController.SIGNUP_URL_MAPPING
};
return PUBLIC_MATCHERS;
}
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
}
}
Run Code Online (Sandbox Code Playgroud)
简而言之,您/rest/**在同一个应用程序中有两个子路径(即和其他子路径),并且您希望为每个子路径应用不同的登录方案。Spring-security 允许您有多种配置,允许这种情况。
我会做这样的事情:
@EnableWebSecurity
public class SecurityConfig {
@Configuration
@Order(1)
public static class ApiSecurityConfiguration
extends WebSecurityConfigurerAdapter {
private final JwtAuthorizationTokenFilter jwtFilter = new ...
private final AuthenticationEntryPoint unauthorizedHandler = new ...
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/rest/**").authorizeRequests()
.and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and()
.addFilter(jwtFilter);
}
}
@Configuration
public static class OtherSecurityConfiguration
extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").defaultSuccessUrl("/bonanza/list")
.failureUrl("/login?error").permitAll()
.and()
.logout().permitAll();
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过这样的配置,JwtAuthorizationTokenFilter应该仅针对匹配的路径激活 。因此我认为您不需要检查JwtAuthorizationTokenFilter.
| 归档时间: |
|
| 查看次数: |
645 次 |
| 最近记录: |