java怎样实现自定义过滤关键词_SpringSecurity学习之自定义过滤器的实现代码

我们系统中的认证场景通常比较复杂,比如说用户被锁定无法登录,限制登录IP等。而SpringSecuriy最基本的是基于用户与密码的形式进行认证,由此可知它的一套验证规范根本无法满足业务需要,因此扩展势在必行。那么我们可以考虑自己定义filter添加至SpringSecurity的过滤器栈当中,来实现我们自己的验证需要。

本例中,基于前篇的数据库的Student表来模拟一个简单的例子:当Student的jointime在当天之后,那么才允许登录

一、创建自己定义的Filter

我们先在web包下创建好几个包并定义如下几个类

17486c25af6e0ce62346184c184b5272.png

CustomerAuthFilter:

package com.bdqn.lyrk.security.study.web.filter;

import com.bdqn.lyrk.security.study.web.authentication.UserJoinTimeAuthentication;

import org.springframework.security.authentication.AuthenticationManager;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.AuthenticationException;

import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;

import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

public class CustomerAuthFilter extends AbstractAuthenticationProcessingFilter {

private AuthenticationManager authenticationManager;

public CustomerAuthFilter(AuthenticationManager authenticationManager) {

super(new AntPathRequestMatcher("/login", "POST"));

this.authenticationManager = authenticationManager;

}

@Override

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {

String username = request.getParameter("username");

UserJoinTimeAuthentication usernamePasswordAuthenticationToken =new UserJoinTimeAuthentication(username);

Authentication authentication = this.authenticationManager.authenticate(usernamePasswordAuthenticationToken);

if (authentication != null) {

super.setContinueChainBeforeSuccessfulAuthentication(true);

}

return authentication;

}

}

该类继承AbstractAuthenticationProcessingFilter,这个filter的作用是对最基本的用户验证的处理,我们必须重写attemptAuthentication方法。Authentication接口表示授权接口,通常情况下业务认证通过时会返回一个这个对象。super.setContinueChainBeforeSuccessfulAuthentication(true) 设置成true的话,会交给其他过滤器处理。

二、定义UserJoinTimeAuthentication

package com.bdqn.lyrk.security.study.web.authentication;

import org.springframework.security.authentication.AbstractAuthenticationToken;

public class UserJoinTimeAuthentication extends AbstractAuthenticationToken {

private String username;

public UserJoinTimeAuthentication(String username) {

super(null);

this.username = username;

}

@Override

public Object getCredentials() {

return null;

}

@Override

public Object getPrincipal() {

return username;

}

}

自定义授权方式,在这里接收username的值处理,其中getPrincipal我们可以用来存放登录名,getCredentials可以存放密码,这些方法来自于Authentication接口

三、定义AuthenticationProvider

package com.bdqn.lyrk.security.study.web.authentication;

import com.bdqn.lyrk.security.study.app.pojo.Student;

import org.springframework.security.authentication.AuthenticationProvider;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.AuthenticationException;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import java.util.Date;

/**

* 基本的验证方式

*

* @author chen.nie

* @date 2018/6/12

**/

public class UserJoinTimeAuthenticationProvider implements AuthenticationProvider {

private UserDetailsService userDetailsService;

public UserJoinTimeAuthenticationProvider(UserDetailsService userDetailsService) {

this.userDetailsService = userDetailsService;

}

/**

* 认证授权,如果jointime在当前时间之后则认证通过

* @param authentication

* @return

* @throws AuthenticationException

*/

@Override

public Authentication authenticate(Authentication authentication) throws AuthenticationException {

String username = (String) authentication.getPrincipal();

UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

if (!(userDetails instanceof Student)) {

return null;

}

Student student = (Student) userDetails;

if (student.getJoinTime().after(new Date()))

return new UserJoinTimeAuthentication(username);

return null;

}

/**

* 只处理UserJoinTimeAuthentication的认证

* @param authentication

* @return

*/

@Override

public boolean supports(Class> authentication) {

return authentication.getName().equals(UserJoinTimeAuthentication.class.getName());

}

}

AuthenticationManager会委托AuthenticationProvider进行授权处理,在这里我们需要重写support方法,该方法定义Provider支持的授权对象,那么在这里我们是对UserJoinTimeAuthentication处理。

四、WebSecurityConfig

package com.bdqn.lyrk.security.study.app.config;

import com.bdqn.lyrk.security.study.app.service.UserService;

import com.bdqn.lyrk.security.study.web.authentication.UserJoinTimeAuthenticationProvider;

import com.bdqn.lyrk.security.study.web.filter.CustomerAuthFilter;

import org.springframework.beans.factory.annotation.Autowired;

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.web.authentication.UsernamePasswordAuthenticationFilter;

/**

* spring-security的相关配置

*

* @author chen.nie

* @date 2018/6/7

**/

@EnableWebSecurity

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired

private UserService userService;

@Override

protected void configure(HttpSecurity http) throws Exception {

/*

1.配置静态资源不进行授权验证

2.登录地址及跳转过后的成功页不需要验证

3.其余均进行授权验证

*/

http.

authorizeRequests().antMatchers("/static/**").permitAll().

and().authorizeRequests().antMatchers("/user/**").hasRole("7022").

and().authorizeRequests().anyRequest().authenticated().

and().formLogin().loginPage("/login").successForwardUrl("/toIndex").permitAll()

.and().logout().logoutUrl("/logout").invalidateHttpSession(true).deleteCookies().permitAll()

;

http.addFilterBefore(new CustomerAuthFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);

}

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

//设置自定义userService

auth.userDetailsService(userService);

auth.authenticationProvider(new UserJoinTimeAuthenticationProvider(userService));

}

@Override

public void configure(WebSecurity web) throws Exception {

super.configure(web);

}

}

在这里面我们通过HttpSecurity的方法来添加我们自定义的filter,一定要注意先后顺序。在AuthenticationManagerBuilder当中还需要添加我们刚才定义的AuthenticationProvider

启动成功后,我们将Student表里的jointime值改为早于今天的时间,进行登录可以发现:

4d86da1361e3f813e6988e1ed313cb26.png

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值