java token身份认证,基于Spring Security Token的身份验证

I have a rest api where I am authenticating using spring security Basic Authorization where client sends username and password for each request.

Now, I wanted to implement token based authentication where I will send a token in response header when user is authenticated at first. For further requests, client can include that token in the header which will be used to authenticate the user to the resources. I have two authentication providers tokenAuthenticationProvider and daoAuthenticationProvider

@Component

public class TokenAuthenticationProvider implements AuthenticationProvider {

@Autowired

private TokenAuthentcationService service;

@Override

public Authentication authenticate(final Authentication authentication) throws AuthenticationException {

final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

final HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();

final String token = request.getHeader(Constants.AUTH_HEADER_NAME);

final Token tokenObj = this.service.getToken(token);

final AuthenticationToken authToken = new AuthenticationToken(tokenObj);

return authToken;

}

@Override

public boolean supports(final Class> authentication) {

return AuthenticationToken.class.isAssignableFrom(authentication);

}

}

And in daoAuthenticationProvider I am setting custom userDetailsService and authenticating against user login details by fetching it from the database (which is working fine as long as user name and password are passed using Authorization:Basic bGllQXBpVXNlcjogN21wXidMQjRdTURtR04pag== as header)

But when I include token in the header using X-AUTH-TOKEN (which is Constants.AUTH_HEADER_NAME), tokenAuthenticationProvider is not being called. I am getting error as

{"timestamp":1487626368308,"status":401,"error":"Unauthorized","message":"Full authentication is required to access this resource","path":"/find"}

And here is how I am adding authentication providers.

@Override

public void configure(final AuthenticationManagerBuilder auth) throws Exception {

final UsernamePasswordAuthenticationProvider daoProvider = new

UsernamePasswordAuthenticationProvider(this.service, this.passwordEncoder());

auth.authenticationProvider(this.tokenAuthenticationProvider);

auth.authenticationProvider(daoProvider);

}

Please suggest how can I implement Token based authentication without hurting the current behavior of spring security.

解决方案

Here is how I was able to implement token based authentication and basic authentication

SpringSecurityConfig.java

@Configuration

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter

{

@Override

public void configure(final AuthenticationManagerBuilder auth) throws Exception

{

auth.userDetailsService(this.participantService).passwordEncoder(this.passwordEncoder());

}

@Override

protected void configure(final HttpSecurity http) throws Exception

{

//Implementing Token based authentication in this filter

final TokenAuthenticationFilter tokenFilter = new TokenAuthenticationFilter();

http.addFilterBefore(tokenFilter, BasicAuthenticationFilter.class);

//Creating token when basic authentication is successful and the same token can be used to authenticate for further requests

final CustomBasicAuthenticationFilter customBasicAuthFilter = new CustomBasicAuthenticationFilter(this.authenticationManager() );

http.addFilter(customBasicAuthFilter);

}

}

TokenAuthenticationFilter.java

public class TokenAuthenticationFilter extends GenericFilterBean

{

@Override

public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)

throws IOException, ServletException

{

final HttpServletRequest httpRequest = (HttpServletRequest)request;

//extract token from header

final String accessToken = httpRequest.getHeader("header-name");

if (null != accessToken) {

//get and check whether token is valid ( from DB or file wherever you are storing the token)

//Populate SecurityContextHolder by fetching relevant information using token

final User user = new User(

"username",

"password",

true,

true,

true,

true,

authorities);

final UsernamePasswordAuthenticationToken authentication =

new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());

SecurityContextHolder.getContext().setAuthentication(authentication);

}

chain.doFilter(request, response);

}

}

CustomBasicAuthenticationFilter.java

@Component

public class CustomBasicAuthenticationFilter extends BasicAuthenticationFilter {

@Autowired

public CustomBasicAuthenticationFilter(final AuthenticationManager authenticationManager) {

super(authenticationManager);

}

@Override

protected void onSuccessfulAuthentication(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response, final Authentication authResult) {

//Generate Token

//Save the token for the logged in user

//send token in the response

response.setHeader("header-name" , "token");

}

}

As our CustomBasicAuthenticationFilter has been configured and added as a filter to the spring security,

Whenever basic authentication is successful the request will be redirected to onSuccessfulAuthentication where we set the token and send it in the response with some header "header-name".

If "header-name" is sent for further request, then the request will go through TokenAuthenticationFilter first before attempting to try Basic Authentication.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值