spring Security4 和 oauth2整合 注解+xml混合使用(验证码等额外数据验证)

spring Security4 和 oauth2整合(验证码等额外数据验证)

上一篇写的自定义用户名密码验证,这里写验证码的验证,或者其他信息的验证。

git地址:https://gitee.com/xiaoyaofeiyang/OauthUmp

spring Security4 和 oauth2整合 注解+xml混合使用(基础运行篇)
spring Security4 和 oauth2整合 注解+xml混合使用(进阶篇)
spring Security4 和 oauth2整合 注解+xml混合使用(授权码篇)
spring Security4 和 oauth2整合 注解+xml混合使用(注意事项篇)
spring Security4 和 oauth2整合 注解+xml混合使用(替换6位的授权码)
spring Security4 和 oauth2整合 注解+xml混合使用(替换用户名密码认证)
spring Security4 和 oauth2整合 注解+xml混合使用(验证码等额外数据验证)

验证码等额外数据获取逻辑

新增OauthAddUserDetails继承WebAuthenticationDetails,这里从request里拿到额外的参数。对比验证码,我们需要有一个接口去更新验证码,更新完放到session里,只有这个地方可以拿到request,所以我就在这里把session里的验证码也拿出来。

package com.ump.oauth.detail;

import java.util.Collection;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import com.ump.domain.AppUser;

public class OauthAddUserDetails extends WebAuthenticationDetails{
     /**
     * 
     */
    private static final long serialVersionUID = 6975601077710753878L;
    private final String token;
    private final String sessionToken;

    public OauthAddUserDetails(HttpServletRequest request) {
        super(request);
        token = request.getParameter("imgtoken");
        sessionToken = (String) request.getSession().getAttribute("imgtoken");
    }

    public String getToken() {
        return token;
    }

    public String getSessionToken() {
        return sessionToken;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(super.toString()).append("; Token: ").append(this.getToken());
        return sb.toString();
    }

}

增加AuthenticationDetailsSource

AuthenticationDetailsSource是需要配置在spring security里的WebSecurityConfigurerAdapter子类里。

package com.ump.oauth.part;

import javax.servlet.http.HttpServletRequest;

import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;

import com.ump.oauth.detail.OauthAddUserDetails;

@Component("oauthAuthenticationDetailsSource")
public class OauthAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {

    @Override
    public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
        return new OauthAddUserDetails(context);
    }


}

AuthenticationProvider的认证逻辑增加验证码处理

对比验证码,这里我们做验证码的对比工作。部分代码是上一篇讲到的,按照自己逻辑删减即可。

package com.ump.oauth.part;

import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

import com.ump.oauth.detail.OauthAddUserDetails;
import com.ump.oauth.detail.OauthUserDetails;

@Component
public class OauthAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private OauthUserDetailsService oauthUserDetailsService;

    /**
     * 自定义验证方式
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        //验证码等校验
        OauthAddUserDetails details = (OauthAddUserDetails) authentication.getDetails();

        System.out.println(details.getToken() + "+++++++++++++++++" + details.getSessionToken());
        if (!details.getToken().equalsIgnoreCase(details.getSessionToken())) {
            throw new BadCredentialsException("验证码错误。");
        }

        //用户名密码校验
        OauthUserDetails oauthUserDetails = (OauthUserDetails) oauthUserDetailsService
                .loadUserByUsername(authentication.getName());
        System.out.println(authentication.getName() + "+++++++++++++++++" + authentication.getCredentials());
        if (!oauthUserDetails.getUserName().equals(authentication.getName())
                || !oauthUserDetails.getPassword().equals(authentication.getCredentials())) {
            throw new BadCredentialsException("用户名或密码错误。");
        }
        Collection<? extends GrantedAuthority> authorities = oauthUserDetails.getAuthorities();
        return new UsernamePasswordAuthenticationToken(oauthUserDetails.getUsername(), oauthUserDetails.getPassword(),
                authorities);
    }

    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }
}

配置authenticationDetailsSource

只需要一个autowired和HttpSecurity一个.authenticationDetailsSource(authenticationDetailsSource)即可。我这里代码多,删减即可。

package com.ump.oauth.config;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.authentication.AuthenticationManager;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import com.ump.oauth.part.OauthAuthenticationProvider;

@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("myClientDetailsService")
    private ClientDetailsService clientDetailsService;

    @Autowired
    private OauthAuthenticationProvider oauthAuthenticationProvider; 

    @Autowired
    @Qualifier("oauthAuthenticationDetailsSource")
    private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(oauthAuthenticationProvider);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        SimpleUrlAuthenticationFailureHandler hander = new SimpleUrlAuthenticationFailureHandler();
        hander.setUseForward(true);
        hander.setDefaultFailureUrl("/authlogin.jsp");

        http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/oauth/token")
        .permitAll().and()
        .formLogin().loginPage("/authlogin.jsp")
        .usernameParameter("userName").passwordParameter("userPwd")
        .authenticationDetailsSource(authenticationDetailsSource)
//      .loginProcessingUrl("/login").failureUrl("/index1.jsp")
        .loginProcessingUrl("/login").failureHandler(hander)
        .and().logout().logoutUrl("/logout");
        http.authorizeRequests().antMatchers("/user/**").authenticated();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    @Autowired
    public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
        TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
        handler.setTokenStore(tokenStore);
        handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
        handler.setClientDetailsService(clientDetailsService);
        return handler;
    }

    @Bean
    @Autowired
    public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
        TokenApprovalStore store = new TokenApprovalStore();
        store.setTokenStore(tokenStore);
        return store;
    }

}

这样就可以了,需要其他信息验证,我们就从request里面拿东西就是了。

猜你喜欢

转载自blog.csdn.net/feiyangtianyao/article/details/78728147