前言
转载:https://www.cnblogs.com/7788IT/articles/11626900.html
代码
在上面的代码上面,又加了一些常用的配置
- 资源服务配置
import com.oauth2.server.system.init.oauth2.handler.MyAuthenticationFailureHandler;
import com.oauth2.server.system.init.oauth2.handler.MyAuthenticationSucessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
/**
* @author :qilong sun
* @date :Created in 2020/7/10 16:56
* @description:资源服务器配置;configure配置:https://www.cnblogs.com/7788IT/articles/11626900.html
* @modified By:
* @version: V1.0$
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private MyAuthenticationSucessHandler authenticationSucessHandler;
@Autowired
private MyAuthenticationFailureHandler authenticationFailureHandler;
@Override
public void configure(HttpSecurity httpSecurity) throws Exception {
// 开启授权认证
httpSecurity.authorizeRequests().anyRequest().authenticated();
// 登录地址
httpSecurity.formLogin().loginProcessingUrl("/login");
// 处理登录成功
httpSecurity.formLogin().successHandler(authenticationSucessHandler);
// 处理登录失败
httpSecurity.formLogin().failureHandler(authenticationFailureHandler);
// 开启跨域共享,跨域伪造请求限制=无效
httpSecurity.cors().and().csrf().disable();
}
}
- 成功处理
import com.alibaba.fastjson.JSONObject;
import com.basics.util.common.dto.RestCode;
import com.basics.util.common.dto.RestResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
/**
* @author :qilong sun
* @date :Created in 2020/7/15 10:59
* @description:
* @modified By:
* @version: V1.0$
*/
@Component
@Slf4j
public class MyAuthenticationSucessHandler implements AuthenticationSuccessHandler {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationServerTokenServices authorizationServerTokenServices;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
// 1. 从请求头中获取 ClientId
String header = request.getHeader("Authorization");
if (header == null || !header.startsWith("Basic ")) {
throw new UnapprovedClientAuthenticationException("请求头中无client信息");
}
String[] tokens = this.extractAndDecodeHeader(header, request);
String clientId = tokens[0];
String clientSecret = tokens[1];
TokenRequest tokenRequest = null;
// 2. 通过 ClientDetailsService 获取 ClientDetails
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
// 3. 校验 ClientId和 ClientSecret的正确性
if (clientDetails == null) {
throw new UnapprovedClientAuthenticationException("clientId:" + clientId + "对应的信息不存在");
} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
throw new UnapprovedClientAuthenticationException("clientSecret不正确");
} else {
// 4. 通过 TokenRequest构造器生成 TokenRequest
tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), "custom");
}
// 5. 通过 TokenRequest的 createOAuth2Request方法获取 OAuth2Request
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
// 6. 通过 Authentication和 OAuth2Request构造出 OAuth2Authentication
OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
// 7. 通过 AuthorizationServerTokenServices 生成 OAuth2AccessToken
OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);
// 8. 返回 Token
log.info("登录成功");
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
RestResponse restResponse = new RestResponse();
restResponse.setCode(RestCode.SUCCESS.getCode());
restResponse.setMsg("登录成功");
restResponse.setData(new ObjectMapper().writeValueAsString(token));
response.getWriter().write(JSONObject.toJSONString(restResponse));
}
private String[] extractAndDecodeHeader(String header, HttpServletRequest request) {
byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);
byte[] decoded;
try {
decoded = Base64.getDecoder().decode(base64Token);
} catch (IllegalArgumentException var7) {
throw new BadCredentialsException("Failed to decode basic authentication token");
}
String token = new String(decoded, StandardCharsets.UTF_8);
int delim = token.indexOf(":");
if (delim == -1) {
throw new BadCredentialsException("Invalid basic authentication token");
} else {
return new String[]{token.substring(0, delim), token.substring(delim + 1)};
}
}
}
- 失败处理
import com.alibaba.fastjson.JSONObject;
import com.basics.util.common.dto.RestCode;
import com.basics.util.common.dto.RestResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.*;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author :qilong sun
* @date :Created in 2020/7/15 10:59
* @description:
* @modified By:
* @version: V1.0$
*/
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Resource
private ObjectMapper mapper;
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
RestResponse restResponse = new RestResponse();
if(e instanceof AccessDeniedHandler){
restResponse.setCode(RestCode.SUCCESS.getCode());
restResponse.setMsg("登录成功");
}else if(e instanceof AuthenticationEntryPoint){
restResponse.setCode(RestCode.FAILURE.getCode());
restResponse.setMsg("登录过期或未登录");
}else if(e instanceof AccountExpiredException){
restResponse.setCode(RestCode.FAILURE.getCode());
restResponse.setMsg("账户已过期");
}else if(e instanceof BadCredentialsException){
restResponse.setCode(RestCode.FAILURE.getCode());
restResponse.setMsg("用户名或密码错误");
}else if(e instanceof DisabledException){
restResponse.setCode(RestCode.FAILURE.getCode());
restResponse.setMsg("账户已禁用");
}else if(e instanceof CredentialsExpiredException){
restResponse.setCode(RestCode.FAILURE.getCode());
restResponse.setMsg("证书已过期");
}else if(e instanceof LockedException){
restResponse.setCode(RestCode.FAILURE.getCode());
restResponse.setMsg("用户账户已被锁定");
}else if(e instanceof InternalAuthenticationServiceException){
restResponse.setCode(RestCode.FAILURE.getCode());
restResponse.setMsg("内部身份验证服务异常");
}else{
restResponse.setCode(RestCode.ERROR.getCode());
restResponse.setMsg(RestCode.ERROR.getMsg());
}
httpServletResponse.getWriter().write(JSONObject.toJSONString(restResponse));
}
}