• springcloud中oauth工作流程


    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;
        }
    }
    

      

    第四部  数据请求流程如下

    1.请求来到控制器

    2.如果“**/findTaskRate”的这个请求需要权限。那么根据在访问中配置的,注意要写成localhost,不要写成ip,写成ip在服务器上能运行,本地不行

    这个服务在鉴权服务上门。通过token如果能够获取用,鉴权成功。否则token无效。

    鉴权成功之后,进入控制器的方法中,往下执行。

  • 相关阅读:
    Python学习笔记--8.3 函数--返回值
    Python学习笔记--8.2 函数--默认值参数
    Python学习笔记--9 非空即真,非零即真
    [Robot Framework] 支持python 3 的 robot framework 安装
    Mysql DB 无法创建 function,报错:ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL
    vue项目中console.log报错 No Console
    git命令合并分支代码
    远程桌面连接时如何使用本地扬声器和麦克风
    [Grafana] 如何把不同series的点用线连接起来
    POM 文件参考
  • 原文地址:https://www.cnblogs.com/longsanshi/p/9667141.html
Copyright © 2020-2023  润新知