1. 程式人生 > >springcloud中oauth工作流程

springcloud中oauth工作流程

lan enable app sci exceptio startup see uid rto

1.第一步登錄獲取token

通過oauth服務,進行登錄。返回token

 @ApiOperation(value="登錄", notes="登錄",httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    //@PostMapping("/generatorToken")
    @RequestMapping(value="/generatorToken")
    public ResponseEntity<OAuth2AccessToken> token(String username,String password, String vrifyCode, String captchaFlag) throws HttpRequestMethodNotSupportedException {
        
if(captchaFlag != null && !captchaFlag.equals("")){ boolean flag = doCaptchaValidate(captchaFlag,vrifyCode); if(!flag){ throw new InvalidGrantException("驗證碼不正確!"); } } Map<String, String> requestParameters = new HashMap<>(); requestParameters.put(
"grant_type","password");//自己設置 requestParameters.put("client_id","client_id");//自己設置 requestParameters.put("client_secret","client_secret");//自己設置 String clientId = (String)requestParameters.get("client_id"); String grantType = (String)requestParameters.get("grant_type"); Set
<String> scopes = new HashSet<>(); scopes.add("all"); TokenRequest tokenRequest = new TokenRequest(requestParameters, clientId, scopes, grantType); ClientDetails client = this.clientDetailsService.loadClientByClientId(tokenRequest.getClientId()); OAuth2RequestFactory oAuth2RequestFactory = authorizationServerEndpointsConfiguration.getEndpointsConfigurer().getOAuth2RequestFactory(); OAuth2Authentication oAuth2Authentication = null; Map<String, String> parameters = new LinkedHashMap(tokenRequest.getRequestParameters()); parameters.remove("password"); Authentication userAuth = new UsernamePasswordAuthenticationToken(username, password); ((AbstractAuthenticationToken)userAuth).setDetails(parameters); try { userAuth = this.authenticationManager.authenticate(userAuth); } catch (AccountStatusException var8) { throw new InvalidGrantException(var8.getMessage()); } catch (BadCredentialsException var9) { throw new InvalidGrantException(var9.getMessage()); } if (userAuth != null && userAuth.isAuthenticated()) { OAuth2Request storedOAuth2Request = oAuth2RequestFactory.createOAuth2Request(client, tokenRequest); oAuth2Authentication = new OAuth2Authentication(storedOAuth2Request, userAuth); } else { throw new InvalidGrantException("Could not authenticate user: " + username); } OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication); return this.getResponse(oAuth2AccessToken); }

第二步 自定義oauth攔截器,這裏設置了

customPrincipalExtractor,下面粉紅色代碼
package com.ycsys.business.config;

import java.nio.charset.StandardCharsets;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationManager;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;

import com.ycsys.business.dto.ResponseEx;

/**
 * Created by lixiaoxin on 2017/9/25.
 *
 * @author lixiaoxin
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private static final Logger LOG = LoggerFactory.getLogger(ResourceServerConfig.class);

//    @Value("${security.oauth2.resource.user-info-uri}")
//    private String userInfoUri;

    @Resource
    private UserInfoTokenServices userInfoTokenServices;

    @Resource
    private CustomPrincipalExtractor customPrincipalExtractor;

    @Override
    public void configure(HttpSecurity http) throws Exception {

        //自定義oauth2攔截器
        OAuth2AuthenticationProcessingFilter f = new OAuth2AuthenticationProcessingFilter();
        OAuth2AuthenticationEntryPoint oAuth2AuthenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        oAuth2AuthenticationEntryPoint.setExceptionTranslator(webResponseExceptionTranslator());
        f.setAuthenticationEntryPoint(oAuth2AuthenticationEntryPoint);
        OAuth2AuthenticationManager o = new OAuth2AuthenticationManager();
        //dt.setTokenStore(tokenStore());
        userInfoTokenServices.setPrincipalExtractor(customPrincipalExtractor);
        o.setTokenServices(userInfoTokenServices);
        f.setAuthenticationManager(o);
        //為空情況自定義返回體
        http.exceptionHandling()
                .authenticationEntryPoint(
                        (request, response,authException)-> {
                        try {
                            ObjectMapper m = new ObjectMapper();
                            String json = m.writeValueAsString(new ResponseEx().error("token不能為空"));
                            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                            response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
                            response.getWriter().write(json);
                        } catch (Exception e1) {
                            e1.printStackTrace();
                        }
        }
        )
                //.defaultAuthenticationEntryPointFor()
                //.accessDeniedHandler(accessDeniedHandler);    // You‘re using the autowired members above.
                .and()
                .authorizeRequests()
//                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
//                    public <O extends FilterSecurityInterceptor> O postProcess(O fsi) {
//                        fsi.set
//                        return fsi;
//                    }})
                //.requestMatchers(CorsUtils::isCorsRequest).permitAll()
                .antMatchers("/swagger-ui.html","/webjars/**","/swagger-ui.html/**","/swagger-resources/**","/v2/**"
                ,"/rest/**","/geometry/**","/wechat/**","/files/**","/user/validateUserName","/user/registerFirst"
                ,"/user/registerSecond","/user/sendRegisterSMS","/user/sendFindPwdSMS","/user/findPwdFirst","/user/findPwdSecond","/user/PWUpdatePassword"
                ,"/user/sendBindingSMS","/ParkDynamics/**","/Animal/**","/AnimalType/**","/AnimalScience/**","/AnimalMusic/**",
                "/AnimalClass/**","/feedback/**","/Guide/**","/helpCenter/**","/Notice/**","/VoiceExplain/**","/WeChatReply/weChatRequest"
                ,"/ThemePavilions/**","/Activity/**","/AnimalFeed/**","/test/**","/location/findUserRealTimeLocation","/EmergencyStartup/**"
                ,"/convenientService/**","/traffic/**","/msg/**","/rulesRegulations/**","/ApeCource/**",
                "/EmergencyPlanModel/findByTypeName").permitAll()
                .anyRequest().authenticated() //開啟網關和授權
                //.anyRequest().permitAll()//不需要通過網關和授權即可訪問
                .and()
                .addFilterBefore(f, AbstractPreAuthenticatedProcessingFilter.class)
                .httpBasic();

    }

//    @Bean
//    // very important notice: method name should be exactly "userInfoTokenServices"
//    public ResourceServerTokenServices userInfoTokenServices() {
//        CustomUserInfoTokenService serv = new CustomUserInfoTokenService(userInfoUri, null);
//        return serv;
//    }

    //自定義返回體
    @Bean
    public WebResponseExceptionTranslator webResponseExceptionTranslator() {
        return new DefaultWebResponseExceptionTranslator() {

            @Override
            public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
                ResponseEntity<OAuth2Exception> responseEntity = super.translate(e);
//                OAuth2Exception body = responseEntity.getBody();
                HttpHeaders headers = new HttpHeaders();
                headers.setAll(responseEntity.getHeaders().toSingleValueMap());
                ResponseEx ex = new ResponseEx().error(ErrorCode.ERROR,"無效的token");
                return new ResponseEntity(ex, headers, responseEntity.getStatusCode());
            }
        };
    }

}

第三步 實現

PrincipalExtractor 
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.resource.PrincipalExtractor;
import org.springframework.stereotype.Component;

import com.ycsys.business.common.EhCacheUtils;
import com.ycsys.business.entity.User;
import com.ycsys.business.repository.UserRepository;

/**
 * Created by lixiaoxin on 2018/2/5.
 */
@Component
public class CustomPrincipalExtractor implements PrincipalExtractor {

    @Autowired
    private UserRepository userRepository;

    private static final String[] PRINCIPAL_KEYS = new String[]{"user", "username", "userid", "user_id", "login", "id", "name"};

    @Override
    public Object extractPrincipal(Map<String, Object> map) {

        for(int i = 0; i < PRINCIPAL_KEYS.length; ++i) {
            String key = PRINCIPAL_KEYS[i];
            if (map.containsKey(key)) {
                if(key.equals("user")){
                    Object obj = map.get(key);
                    Map m = (Map) obj;
                    Integer id = (Integer) m.get("id");
                    Object object = EhCacheUtils.get("users", id.toString());
                    User user=null;
                    if(object==null){
                    	  user = userRepository.getById(id.longValue());
                          EhCacheUtils.put("users", id.toString(), user);
                    }else{
                    	user=(User)object;
                    }
                    return user;
                }else {
                    return map.get(key);
                }
            }
        }

        return null;
    }
}

  

第四部 如何使用

技術分享圖片

springcloud中oauth工作流程