map = new HashMap<>(8);
+ map.put(SecurityConstants.USER_INDEX_KEY, user.getUserIndex());
+ map.put(SecurityConstants.USER_TYPE, user.getType());
+ map.put(SecurityConstants.USER_NICKNAME_KEY, user.getNickName());
+ map.put(SecurityConstants.CLIENT_ID_KEY, clientId);
+ map.put(SecurityConstants.DEPT_INDEX_KEY, user.getDeptIndex());
+ map.put(SecurityConstants.USER_HEAD_KEY, user.getHeadSculpture());
+ if (StrUtil.isNotBlank(user.getAuthenticationMethod())) {
+ map.put(SecurityConstants.AUTHENTICATION_METHOD, user.getAuthenticationMethod());
+ }
+ ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(map);
+ return accessToken;
+ };
+ }
+
+
+ /**
+ * 配置自定义密码认证过滤器
+ * @param security .
+ */
+ @Override
+ public void configure(AuthorizationServerSecurityConfigurer security) {
+ CustomClientCredentialsTokenEndpointFilter endpointFilter = new CustomClientCredentialsTokenEndpointFilter(security);
+ endpointFilter.afterPropertiesSet();
+ endpointFilter.setAuthenticationEntryPoint(authenticationEntryPoint());
+ security.addTokenEndpointAuthenticationFilter(endpointFilter);
+
+ security
+ .authenticationEntryPoint(authenticationEntryPoint())
+ /* .allowFormAuthenticationForClients()*/ //如果使用表单认证则需要加上
+ .tokenKeyAccess("permitAll()")
+ .checkTokenAccess("isAuthenticated()");
+ }
+
+
+
+ @Bean
+ public DaoAuthenticationProvider authenticationProvider() {
+ DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+ provider.setHideUserNotFoundExceptions(false);
+ provider.setUserDetailsService(userDetailsService);
+ provider.setPasswordEncoder(passwordEncoder);
+ return provider;
+ }
+
+}
diff --git a/carry_capacity/src/main/java/com/njcn/product/auth/config/WebSecurityConfig.java b/carry_capacity/src/main/java/com/njcn/product/auth/config/WebSecurityConfig.java
new file mode 100644
index 0000000..4ce2e43
--- /dev/null
+++ b/carry_capacity/src/main/java/com/njcn/product/auth/config/WebSecurityConfig.java
@@ -0,0 +1,110 @@
+package com.njcn.product.auth.config;
+
+
+import com.njcn.product.auth.filter.AuthGlobalFilter;
+import com.njcn.product.auth.security.provider.Sm4AuthenticationProvider;
+import com.njcn.product.auth.security.provider.SmsAuthenticationProvider;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+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.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * @author hongawen
+ */
+@Slf4j
+@Configuration
+@EnableWebSecurity
+@RequiredArgsConstructor
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ private final UserDetailsService sysUserDetailsService;
+
+ private final Sm4AuthenticationProvider sm4AuthenticationProvider;
+
+ private final SmsAuthenticationProvider smsAuthenticationProvider;
+ private final AuthGlobalFilter authGlobalFilter;
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .authorizeRequests()
+ .antMatchers("/user/generateSm2Key","/oauth/token","/theme/getTheme").permitAll()
+ .antMatchers("/webjars/**","/doc.html","/swagger-resources/**","/v2/api-docs").permitAll()
+ .anyRequest().authenticated()
+ .and()
+ .csrf().disable();
+ http.addFilterAfter(authGlobalFilter, UsernamePasswordAuthenticationFilter.class);
+
+ }
+
+ /**
+ * 认证管理对象
+ *
+ * @throws Exception .
+ * @return .
+ */
+ @Override
+ @Bean
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+
+
+ @Override
+ public void configure(AuthenticationManagerBuilder auth) {
+ auth.authenticationProvider(daoAuthenticationProvider());
+ }
+
+
+
+ /**
+ * 重写父类自定义AuthenticationManager 将provider注入进去
+ * 当然我们也可以考虑不重写 在父类的manager里面注入provider
+ */
+ @Bean
+ @Override
+ protected AuthenticationManager authenticationManager(){
+ return new ProviderManager(sm4AuthenticationProvider,smsAuthenticationProvider);
+ }
+
+
+
+ /**
+ * 用户名密码认证授权提供者
+ */
+ @Bean
+ public DaoAuthenticationProvider daoAuthenticationProvider() {
+ DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
+ provider.setUserDetailsService(sysUserDetailsService);
+ provider.setPasswordEncoder(passwordEncoder());
+ // 是否隐藏用户不存在异常,默认:true-隐藏;false-抛出异常;
+ provider.setHideUserNotFoundExceptions(false);
+ return provider;
+ }
+
+ /**
+ * 密码编码器
+ *
+ * 委托方式,根据密码的前缀选择对应的encoder,例如:{bcypt}前缀->标识BCYPT算法加密;{noop}->标识不使用任何加密即明文的方式
+ * 密码判读 DaoAuthenticationProvider#additionalAuthenticationChecks
+ */
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return PasswordEncoderFactories.createDelegatingPasswordEncoder();
+ }
+
+
+}
diff --git a/carry_capacity/src/main/java/com/njcn/product/auth/controller/AuthController.java b/carry_capacity/src/main/java/com/njcn/product/auth/controller/AuthController.java
new file mode 100644
index 0000000..277fc40
--- /dev/null
+++ b/carry_capacity/src/main/java/com/njcn/product/auth/controller/AuthController.java
@@ -0,0 +1,222 @@
+package com.njcn.product.auth.controller;
+
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONObject;
+import com.nimbusds.jose.jwk.JWKSet;
+import com.nimbusds.jose.jwk.RSAKey;
+
+import com.njcn.common.pojo.annotation.OperateInfo;
+import com.njcn.common.pojo.constant.LogInfo;
+import com.njcn.common.pojo.constant.OperateType;
+import com.njcn.common.pojo.constant.SecurityConstants;
+import com.njcn.common.pojo.dto.UserTokenInfo;
+import com.njcn.common.pojo.enums.common.LogEnum;
+import com.njcn.common.pojo.enums.response.CommonResponseEnum;
+import com.njcn.common.pojo.exception.BusinessException;
+import com.njcn.common.pojo.response.HttpResult;
+import com.njcn.common.utils.HttpResultUtil;
+import com.njcn.common.utils.LogUtil;
+import com.njcn.common.utils.sm.DesUtils;
+import com.njcn.common.utils.sm.Sm2;
+import com.njcn.product.auth.pojo.enums.UserResponseEnum;
+import com.njcn.product.auth.service.IUserService;
+import com.njcn.product.auth.service.UserTokenService;
+import com.njcn.product.auth.utils.AuthPubUtil;
+import com.njcn.redis.utils.RedisUtil;
+
+import com.njcn.web.controller.BaseController;
+import com.njcn.web.utils.RequestUtil;
+import com.njcn.web.utils.RestTemplateUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.security.oauth2.common.OAuth2AccessToken;
+import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.util.UriComponentsBuilder;
+import springfox.documentation.annotations.ApiIgnore;
+
+import javax.servlet.http.HttpServletRequest;
+import java.net.URI;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.interfaces.RSAPublicKey;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author hongawen
+ */
+@Api(tags = "认证中心")
+@Slf4j
+@RestController
+@RequestMapping("/oauth")
+@AllArgsConstructor
+public class AuthController extends BaseController {
+
+
+ private final TokenEndpoint tokenEndpoint;
+
+ private final KeyPair keyPair;
+
+ private final RedisUtil redisUtil;
+
+ private final IUserService userService;
+
+
+ private final UserTokenService userTokenService;
+
+
+ @ApiIgnore
+ @OperateInfo(info = LogEnum.SYSTEM_SERIOUS, operateType = OperateType.AUTHENTICATE)
+ @ApiOperation("登录认证")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = SecurityConstants.GRANT_TYPE, defaultValue = "password", value = "授权模式", required = true),
+ @ApiImplicitParam(name = SecurityConstants.CLIENT_ID, defaultValue = "njcn", value = "Oauth2客户端ID", required = true),
+ @ApiImplicitParam(name = SecurityConstants.CLIENT_SECRET, defaultValue = "njcnpqs", value = "Oauth2客户端秘钥", required = true),
+ @ApiImplicitParam(name = SecurityConstants.REFRESH_TOKEN, value = "刷新token"),
+ @ApiImplicitParam(name = SecurityConstants.USERNAME, value = "登录用户名"),
+ @ApiImplicitParam(name = SecurityConstants.PASSWORD, value = "登录密码"),
+ @ApiImplicitParam(name = SecurityConstants.IMAGE_CODE, value = "图形验证码"),
+ @ApiImplicitParam(name = SecurityConstants.PHONE, value = "手机号"),
+ @ApiImplicitParam(name = SecurityConstants.SMS_CODE, value = "短信验证码"),
+ })
+ @PostMapping("/token")
+ public Object postAccessToken(@ApiIgnore Principal principal, @RequestParam @ApiIgnore Map parameters) throws HttpRequestMethodNotSupportedException {
+ String methodDescribe = getMethodDescribe("postAccessToken");
+ String username = parameters.get(SecurityConstants.USERNAME);
+
+
+ String grantType = parameters.get(SecurityConstants.GRANT_TYPE);
+ if (grantType.equalsIgnoreCase(SecurityConstants.GRANT_CAPTCHA) || grantType.equalsIgnoreCase(SecurityConstants.REFRESH_TOKEN_KEY)) {
+ username = DesUtils.aesDecrypt(username);
+ } else if (grantType.equalsIgnoreCase(SecurityConstants.GRANT_SMS_CODE)) {
+ //短信方式登录,将手机号赋值为用户名
+ username = parameters.get(SecurityConstants.PHONE);
+ }
+
+
+
+ if (grantType.equalsIgnoreCase(SecurityConstants.REFRESH_TOKEN_KEY)) {
+ //如果是刷新token,需要去黑名单校验
+ userTokenService.judgeRefreshToken(parameters.get(SecurityConstants.REFRESH_TOKEN_KEY));
+ }
+ RequestUtil.saveLoginName(username);
+ OAuth2AccessToken oAuth2AccessToken = tokenEndpoint.postAccessToken(principal, parameters).getBody();
+ //用户的登录名&密码校验成功后,判断当前该用户是否可以正常使用系统
+ if (!grantType.equalsIgnoreCase(SecurityConstants.GRANT_SMS_CODE)) {
+ userService.judgeUserStatus(username);
+ }
+ //登录成功后,记录token信息,并处理踢人效果
+ userTokenService.recordUserInfo(oAuth2AccessToken, RequestUtil.getRealIp());
+ if (!grantType.equalsIgnoreCase(SecurityConstants.PASSWORD)) {
+ return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, oAuth2AccessToken, methodDescribe);
+ } else {
+ return oAuth2AccessToken;
+ }
+ }
+
+ @OperateInfo(info = LogEnum.SYSTEM_SERIOUS, operateType = OperateType.LOGOUT)
+ @ApiOperation("用户登出系统")
+ @DeleteMapping("/logout")
+ public HttpResult