1. 程式人生 > >spring Security4 和 oauth2整合 註解+xml混合使用(驗證碼等額外資料驗證)

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裡面拿東西就是了。