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无效。
鉴权成功之后,进入控制器的方法中,往下执行。