feat: 初始化
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package com.yida.data.auth;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
|
||||
import cc.mrbird.febs.common.security.starter.annotation.EnableFebsCloudResourceServer;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableRedisHttpSession
|
||||
@EnableFebsCloudResourceServer
|
||||
@MapperScan("com.yida.data.auth.mapper")
|
||||
@EnableFeignClients(basePackages = "com.yida.data")
|
||||
public class EduAuthApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(EduAuthApplication.class)
|
||||
.web(WebApplicationType.SERVLET)
|
||||
.run(args);
|
||||
}
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
package com.yida.data.auth.configure;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
|
||||
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
|
||||
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
|
||||
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
|
||||
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
|
||||
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
|
||||
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
|
||||
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
|
||||
import org.springframework.security.oauth2.provider.token.TokenStore;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
|
||||
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
|
||||
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import com.yida.data.auth.properties.FebsAuthProperties;
|
||||
import com.yida.data.auth.service.impl.RedisAuthenticationCodeService;
|
||||
import com.yida.data.auth.service.impl.RedisClientDetailsService;
|
||||
import com.yida.data.auth.translator.FebsWebResponseExceptionTranslator;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* 认证服务器配置
|
||||
*/
|
||||
@Configuration
|
||||
@EnableAuthorizationServer
|
||||
@RequiredArgsConstructor
|
||||
public class FebsAuthorizationServerConfigure extends AuthorizationServerConfigurerAdapter {
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final UserDetailsService userDetailService;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final FebsWebResponseExceptionTranslator exceptionTranslator;
|
||||
private final FebsAuthProperties properties;
|
||||
private final RedisAuthenticationCodeService authenticationCodeService;
|
||||
private final RedisClientDetailsService redisClientDetailsService;
|
||||
private final RedisConnectionFactory redisConnectionFactory;
|
||||
|
||||
@Override
|
||||
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
|
||||
clients.withClientDetails(redisClientDetailsService);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
|
||||
endpoints.tokenStore(tokenStore())
|
||||
.userDetailsService(userDetailService)
|
||||
.authorizationCodeServices(authenticationCodeService)
|
||||
.authenticationManager(authenticationManager)
|
||||
.exceptionTranslator(exceptionTranslator);
|
||||
if (properties.getEnableJwt()) {
|
||||
endpoints.accessTokenConverter(jwtAccessTokenConverter());
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TokenStore tokenStore() {
|
||||
if (properties.getEnableJwt()) {
|
||||
return new JwtTokenStore(jwtAccessTokenConverter());
|
||||
} else {
|
||||
RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
|
||||
// 解决每次生成的 token都一样的问题
|
||||
redisTokenStore.setAuthenticationKeyGenerator(oAuth2Authentication -> UUID.randomUUID().toString());
|
||||
return redisTokenStore;
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TokenApprovalStore tokenApprovalStore(TokenStore tokenStore){
|
||||
TokenApprovalStore tokenApprovalStore = new TokenApprovalStore();
|
||||
tokenApprovalStore.setTokenStore(tokenStore);
|
||||
return tokenApprovalStore;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public DefaultTokenServices defaultTokenServices() {
|
||||
DefaultTokenServices tokenServices = new DefaultTokenServices();
|
||||
|
||||
tokenServices.setTokenStore(tokenStore());
|
||||
tokenServices.setSupportRefreshToken(true);
|
||||
tokenServices.setClientDetailsService(redisClientDetailsService);
|
||||
return tokenServices;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JwtAccessTokenConverter jwtAccessTokenConverter() {
|
||||
JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
|
||||
DefaultAccessTokenConverter defaultAccessTokenConverter = (DefaultAccessTokenConverter) accessTokenConverter.getAccessTokenConverter();
|
||||
DefaultUserAuthenticationConverter userAuthenticationConverter = new DefaultUserAuthenticationConverter();
|
||||
userAuthenticationConverter.setUserDetailsService(userDetailService);
|
||||
defaultAccessTokenConverter.setUserTokenConverter(userAuthenticationConverter);
|
||||
accessTokenConverter.setSigningKey(properties.getJwtAccessKey());
|
||||
return accessTokenConverter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ResourceOwnerPasswordTokenGranter resourceOwnerPasswordTokenGranter(AuthenticationManager authenticationManager, OAuth2RequestFactory oAuth2RequestFactory) {
|
||||
DefaultTokenServices defaultTokenServices = defaultTokenServices();
|
||||
if (properties.getEnableJwt()) {
|
||||
defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter());
|
||||
}
|
||||
return new ResourceOwnerPasswordTokenGranter(authenticationManager, defaultTokenServices, redisClientDetailsService, oAuth2RequestFactory);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DefaultOAuth2RequestFactory oAuth2RequestFactory() {
|
||||
return new DefaultOAuth2RequestFactory(redisClientDetailsService);
|
||||
}
|
||||
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.yida.data.auth.configure;
|
||||
|
||||
import com.yida.data.auth.handler.FebsWebLoginFailureHandler;
|
||||
import com.yida.data.auth.handler.FebsWebLoginSuccessHandler;
|
||||
import com.yida.data.auth.filter.ValidateCodeFilter;
|
||||
import com.yida.data.common.core.entity.constant.EndpointConstant;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
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.password.PasswordEncoder;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* WebSecurity配置
|
||||
*
|
||||
* @author MrBird
|
||||
*/
|
||||
@Order(2)
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
public class FebsSecurityConfigure extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final UserDetailsService userDetailService;
|
||||
private final ValidateCodeFilter validateCodeFilter;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final FebsWebLoginSuccessHandler successHandler;
|
||||
private final FebsWebLoginFailureHandler failureHandler;
|
||||
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
.requestMatchers()
|
||||
.antMatchers(EndpointConstant.OAUTH_ALL, EndpointConstant.LOGIN)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers(EndpointConstant.OAUTH_ALL).authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginPage(EndpointConstant.LOGIN)
|
||||
.loginProcessingUrl(EndpointConstant.LOGIN)
|
||||
.successHandler(successHandler)
|
||||
.failureHandler(failureHandler)
|
||||
.permitAll()
|
||||
.and().csrf().disable()
|
||||
.httpBasic().disable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder);
|
||||
}
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package com.yida.data.auth.controller;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
import com.yida.data.auth.service.OauthClientDetailsService;
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
import com.yida.data.common.core.entity.QueryRequest;
|
||||
import com.yida.data.common.core.entity.auth.OauthClientDetails;
|
||||
import com.yida.data.common.core.exception.FebsException;
|
||||
import com.yida.data.common.core.utils.FebsUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Yuuki
|
||||
*/
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("client")
|
||||
public class OauthClientDetailsController {
|
||||
|
||||
private final OauthClientDetailsService oauthClientDetailsService;
|
||||
|
||||
@GetMapping("check/{clientId}")
|
||||
public boolean checkUserName(@NotBlank(message = "{required}") @PathVariable String clientId) {
|
||||
OauthClientDetails client = this.oauthClientDetailsService.findById(clientId);
|
||||
return client == null;
|
||||
}
|
||||
|
||||
@GetMapping("secret/{clientId}")
|
||||
@PreAuthorize("hasAuthority('client:decrypt')")
|
||||
public FebsResponse getOriginClientSecret(@NotBlank(message = "{required}") @PathVariable String clientId) {
|
||||
OauthClientDetails client = this.oauthClientDetailsService.findById(clientId);
|
||||
String origin = client != null ? client.getOriginSecret() : StringUtils.EMPTY;
|
||||
return new FebsResponse().data(origin);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAuthority('client:view')")
|
||||
public FebsResponse oauthCliendetailsList(QueryRequest request, OauthClientDetails oAuthClientDetails) {
|
||||
Map<String, Object> dataTable = FebsUtil.getDataTable(this.oauthClientDetailsService.findOauthClientDetails(request, oAuthClientDetails));
|
||||
return new FebsResponse().data(dataTable);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAuthority('client:add')")
|
||||
public void addOauthCliendetails(@Valid OauthClientDetails oAuthClientDetails) throws FebsException {
|
||||
try {
|
||||
this.oauthClientDetailsService.createOauthClientDetails(oAuthClientDetails);
|
||||
} catch (Exception e) {
|
||||
String message = "新增客户端失败";
|
||||
log.error(message, e);
|
||||
throw new FebsException(message);
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping
|
||||
@PreAuthorize("hasAuthority('client:delete')")
|
||||
public void deleteOauthCliendetails(@NotBlank(message = "{required}") String clientIds) throws FebsException {
|
||||
try {
|
||||
this.oauthClientDetailsService.deleteOauthClientDetails(clientIds);
|
||||
} catch (Exception e) {
|
||||
String message = "删除客户端失败";
|
||||
log.error(message, e);
|
||||
throw new FebsException(message);
|
||||
}
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
@PreAuthorize("hasAuthority('client:update')")
|
||||
public void updateOauthCliendetails(@Valid OauthClientDetails oAuthClientDetails) throws FebsException {
|
||||
try {
|
||||
this.oauthClientDetailsService.updateOauthClientDetails(oAuthClientDetails);
|
||||
} catch (Exception e) {
|
||||
String message = "修改客户端失败";
|
||||
log.error(message, e);
|
||||
throw new FebsException(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.yida.data.auth.controller;
|
||||
|
||||
import com.yida.data.auth.manager.UserManager;
|
||||
import com.yida.data.auth.service.SecurityService;
|
||||
import com.yida.data.auth.service.ValidateCodeService;
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
import com.yida.data.common.core.entity.constant.StringConstant;
|
||||
import com.yida.data.common.core.exception.ValidateCodeException;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityController {
|
||||
|
||||
private final ValidateCodeService validateCodeService;
|
||||
private final SecurityService securityService;
|
||||
private final UserManager userManager;
|
||||
private final ConsumerTokenServices consumerTokenServices;
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("user")
|
||||
public Principal currentUser(Principal principal) {
|
||||
return principal;
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("captcha")
|
||||
public void captcha(HttpServletRequest request, HttpServletResponse response) throws IOException, ValidateCodeException {
|
||||
validateCodeService.create(request, response);
|
||||
}
|
||||
|
||||
@RequestMapping("login")
|
||||
public String login() {
|
||||
return "login";
|
||||
}
|
||||
|
||||
@RequestMapping("test")
|
||||
public String test() {
|
||||
return "test";
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@DeleteMapping("signout")
|
||||
public FebsResponse signout(HttpServletRequest request, @RequestHeader("Authorization") String token) {
|
||||
token = StringUtils.replace(token, "bearer ", StringConstant.EMPTY);
|
||||
consumerTokenServices.revokeToken(token);
|
||||
return new FebsResponse().message("signout");
|
||||
}
|
||||
|
||||
@ApiOperation("获取学校负责人登录信息")
|
||||
@ResponseBody
|
||||
@GetMapping("/inSchool")
|
||||
public FebsResponse inSchool(Long schoolId) {
|
||||
return new FebsResponse().data(securityService.getSchoolToken(schoolId));
|
||||
}
|
||||
}
|
||||
+225
@@ -0,0 +1,225 @@
|
||||
package com.yida.data.auth.controller;
|
||||
|
||||
import com.yida.data.auth.entity.BindUser;
|
||||
import com.yida.data.auth.service.SocialLoginService;
|
||||
import com.yida.data.common.core.common.ModuleName;
|
||||
import com.yida.data.common.core.common.ResultBean;
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
import com.yida.data.common.core.entity.constant.StringConstant;
|
||||
import com.yida.data.common.core.entity.system.UserConnection;
|
||||
import com.yida.data.common.core.exception.FebsException;
|
||||
import com.yida.data.common.core.utils.FebsUtil;
|
||||
import com.yida.data.log.annotation.OperationLog;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RefreshScope
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("social")
|
||||
public class SocialLoginController {
|
||||
|
||||
private static final String TYPE_LOGIN = "login";
|
||||
private static final String TYPE_BIND = "bind";
|
||||
|
||||
private final SocialLoginService socialLoginService;
|
||||
@Value("${febs.frontUrl}")
|
||||
private String frontUrl;
|
||||
|
||||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param oauthType 第三方登录类型
|
||||
* @param response response
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("/login/{oauthType}/{type}")
|
||||
public void renderAuth(@PathVariable String oauthType, @PathVariable String type, HttpServletResponse response)
|
||||
throws IOException, FebsException {
|
||||
AuthRequest authRequest = socialLoginService.renderAuth(oauthType);
|
||||
response.sendRedirect(
|
||||
authRequest.authorize(oauthType + StringConstant.DOUBLE_COLON + AuthStateUtils.createState()) + "::"
|
||||
+ type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录成功后的回调
|
||||
*
|
||||
* @param oauthType 第三方登录类型
|
||||
* @param callback 携带返回的信息
|
||||
* @return String
|
||||
*/
|
||||
@GetMapping("/{oauthType}/callback")
|
||||
public String login(@PathVariable String oauthType, AuthCallback callback, String state, Model model) {
|
||||
try {
|
||||
FebsResponse febsResponse = null;
|
||||
String type = StringUtils.substringAfterLast(state, StringConstant.DOUBLE_COLON);
|
||||
if (StringUtils.equals(type, TYPE_BIND)) {
|
||||
febsResponse = socialLoginService.resolveBind(oauthType, callback);
|
||||
} else {
|
||||
febsResponse = socialLoginService.resolveLogin(oauthType, callback);
|
||||
}
|
||||
model.addAttribute("response", febsResponse);
|
||||
model.addAttribute("frontUrl", frontUrl);
|
||||
return "result";
|
||||
} catch (Exception e) {
|
||||
String errorMessage = FebsUtil.containChinese(e.getMessage()) ? e.getMessage() : "第三方登录失败";
|
||||
model.addAttribute("error", e.getMessage());
|
||||
return "fail";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定并登录
|
||||
*
|
||||
* @param bindUser bindUser
|
||||
* @param authUser authUser
|
||||
* @return FebsResponse
|
||||
*/
|
||||
@ResponseBody
|
||||
@PostMapping("bind/login")
|
||||
public FebsResponse bindLogin(@Valid BindUser bindUser, AuthUser authUser) throws FebsException {
|
||||
OAuth2AccessToken oAuth2AccessToken = this.socialLoginService.bindLogin(bindUser, authUser);
|
||||
return new FebsResponse().data(oAuth2AccessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册并登录
|
||||
*
|
||||
* @param registUser registUser
|
||||
* @param authUser authUser
|
||||
* @return FebsResponse
|
||||
*/
|
||||
@ResponseBody
|
||||
@PostMapping("sign/login")
|
||||
public FebsResponse signLogin(@Valid BindUser registUser, AuthUser authUser) throws FebsException {
|
||||
OAuth2AccessToken oAuth2AccessToken = this.socialLoginService.signLogin(registUser, authUser);
|
||||
return new FebsResponse().data(oAuth2AccessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绑定
|
||||
*
|
||||
* @param bindUser bindUser
|
||||
* @param authUser authUser
|
||||
*/
|
||||
@ResponseBody
|
||||
@PostMapping("bind")
|
||||
public void bind(BindUser bindUser, AuthUser authUser) throws FebsException {
|
||||
this.socialLoginService.bind(bindUser, authUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解绑
|
||||
*
|
||||
* @param bindUser bindUser
|
||||
* @param oauthType oauthType
|
||||
*/
|
||||
@ResponseBody
|
||||
@DeleteMapping("unbind")
|
||||
public void unbind(BindUser bindUser, String oauthType) throws FebsException {
|
||||
this.socialLoginService.unbind(bindUser, oauthType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户名获取绑定关系
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return FebsResponse
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("connections/{username}")
|
||||
public FebsResponse findUserConnections(@NotBlank(message = "{required}") @PathVariable String username) {
|
||||
List<UserConnection> userConnections = this.socialLoginService.findUserConnections(username);
|
||||
return new FebsResponse().data(userConnections);
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业微信用户授权登录回调
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("qywx/login")
|
||||
@OperationLog(module = ModuleName.AUTH, methods = "企业微信登录")
|
||||
public FebsResponse qywxLogin(String code, String state, String corpId,
|
||||
@ApiParam("0-教师,1-家长") Integer type) {
|
||||
return new FebsResponse().data(socialLoginService.qywxLogin(code, state, corpId, type));
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("app/login")
|
||||
//@OperationLog(module = ModuleName.AUTH, methods = "app登录")
|
||||
public FebsResponse appLogin(@ApiParam("区域id,app") String areaId,
|
||||
@ApiParam("学校Id") Long schoolId,
|
||||
@ApiParam("手机号") String mobile,
|
||||
@ApiParam("app用户id") String userId,
|
||||
@ApiParam("0-教师,1-家长") Integer type) {
|
||||
return new FebsResponse().data(socialLoginService.appLogin(areaId, schoolId, mobile, userId, type));
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@GetMapping("wxpublic/login")
|
||||
//@OperationLog(module = ModuleName.AUTH, methods = "app登录")
|
||||
public FebsResponse wxpublicLogin(String code, String appId,
|
||||
@ApiParam("0-教师,1-家长") Integer type,
|
||||
Long schoolId, String mobile) {
|
||||
return new FebsResponse().data(socialLoginService.wxpublicLogin(code, appId, type, schoolId, mobile));
|
||||
}
|
||||
|
||||
/**
|
||||
* h5登录
|
||||
*
|
||||
* @param schoolId 学校Id
|
||||
* @param mobile 手机号
|
||||
* @param type 0-教师,1-家长
|
||||
* @return com.yida.data.common.core.entity.FebsResponse
|
||||
* @author ZYJ
|
||||
* @date 2022/9/19 17:25
|
||||
*/
|
||||
@ResponseBody
|
||||
@GetMapping("h5/login")
|
||||
public FebsResponse h5Login(@ApiParam("学校Id") Long schoolId, @ApiParam("手机号") String mobile,
|
||||
@ApiParam("0-教师,1-家长") Integer type) {
|
||||
return new FebsResponse().data(socialLoginService.h5Login(schoolId, mobile, type));
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@ApiOperation("检查openId状态")
|
||||
@GetMapping("smart/checkOpenId")
|
||||
public ResultBean<Map<String, Object>> checkOpenId(@RequestParam @ApiParam(value = "微信公众号授权code", required = true) String code,
|
||||
@RequestParam @ApiParam(value = "学校id(链接上附带)", required = true) Long deptId) {
|
||||
return ResultBean.buildSuccess(socialLoginService.checkOpenId(code, deptId));
|
||||
}
|
||||
|
||||
@ResponseBody
|
||||
@ApiOperation("智慧迎新学生端登录接口")
|
||||
@GetMapping("wxPublic/welcome/login")
|
||||
public FebsResponse wxPublicLogin(@RequestParam @ApiParam(value = "微信openId", required = true) String openId,
|
||||
@RequestParam @ApiParam(value = "学校id(链接上附带)", required = true) Long deptId) {
|
||||
return new FebsResponse().data(socialLoginService.wxPublicLogin(openId, deptId));
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.yida.data.auth.controller.in;
|
||||
|
||||
import com.yida.data.auth.service.impl.RedisClientDetailsService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.ClientDetailsService;
|
||||
import org.springframework.security.oauth2.provider.approval.Approval;
|
||||
import org.springframework.security.oauth2.provider.approval.Approval.ApprovalStatus;
|
||||
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RequestMapping("/in/security")
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
public class InSecurityController {
|
||||
|
||||
private final TokenApprovalStore tokenApprovalStore;
|
||||
private final RedisClientDetailsService redisClientDetailsService;
|
||||
|
||||
@ApiOperation("撤销认证")
|
||||
@GetMapping("/revokeApproval")
|
||||
public void revokeApproval(String userName, String clientId) {
|
||||
ClientDetails client = redisClientDetailsService.loadClientByClientId(clientId);
|
||||
List<Approval> approvals = new ArrayList<Approval>();
|
||||
for (String scope : client.getScope()) {
|
||||
approvals.add(new Approval(userName, clientId, scope, new Date(), ApprovalStatus.APPROVED));
|
||||
}
|
||||
tokenApprovalStore.revokeApprovals(approvals);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.yida.data.auth.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Data
|
||||
public class BindUser implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3890998115990166651L;
|
||||
|
||||
@NotBlank(message = "{required}")
|
||||
private String bindUsername;
|
||||
@NotBlank(message = "{required}")
|
||||
private String bindPassword;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.yida.data.auth.filter;
|
||||
|
||||
import com.yida.data.auth.service.ValidateCodeService;
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
import com.yida.data.common.core.entity.constant.EndpointConstant;
|
||||
import com.yida.data.common.core.entity.constant.GrantTypeConstant;
|
||||
import com.yida.data.common.core.entity.constant.ParamsConstant;
|
||||
import com.yida.data.common.core.exception.ValidateCodeException;
|
||||
import com.yida.data.common.core.utils.FebsUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 验证码过滤器
|
||||
*
|
||||
* @author MrBird
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class ValidateCodeFilter extends OncePerRequestFilter {
|
||||
|
||||
private final ValidateCodeService validateCodeService;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(@Nonnull HttpServletRequest httpServletRequest, @Nonnull HttpServletResponse httpServletResponse,
|
||||
@Nonnull FilterChain filterChain) throws ServletException, IOException {
|
||||
String header = httpServletRequest.getHeader(HttpHeaders.AUTHORIZATION);
|
||||
|
||||
RequestMatcher matcher = new AntPathRequestMatcher(EndpointConstant.OAUTH_TOKEN, HttpMethod.POST.toString());
|
||||
if (matcher.matches(httpServletRequest)
|
||||
&& StringUtils.equalsIgnoreCase(httpServletRequest.getParameter(ParamsConstant.GRANT_TYPE), GrantTypeConstant.PASSWORD)) {
|
||||
try {
|
||||
validateCode(httpServletRequest);
|
||||
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
||||
} catch (Exception e) {
|
||||
FebsResponse febsResponse = new FebsResponse();
|
||||
FebsUtil.makeFailureResponse(httpServletResponse, febsResponse.message(e.getMessage()));
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
} else {
|
||||
filterChain.doFilter(httpServletRequest, httpServletResponse);
|
||||
}
|
||||
}
|
||||
|
||||
private void validateCode(HttpServletRequest httpServletRequest) throws ValidateCodeException {
|
||||
String code = httpServletRequest.getParameter(ParamsConstant.VALIDATE_CODE_CODE);
|
||||
String key = httpServletRequest.getParameter(ParamsConstant.VALIDATE_CODE_KEY);
|
||||
validateCodeService.check(key, code);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.yida.data.auth.handler;
|
||||
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
import com.yida.data.common.core.utils.FebsUtil;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.LockedException;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Component
|
||||
public class FebsWebLoginFailureHandler implements AuthenticationFailureHandler {
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException exception) throws IOException {
|
||||
String message;
|
||||
if (exception instanceof BadCredentialsException) {
|
||||
message = "用户名或密码错误!";
|
||||
} else if (exception instanceof LockedException) {
|
||||
message = "用户已被锁定!";
|
||||
} else {
|
||||
message = "认证失败,请联系网站管理员!";
|
||||
}
|
||||
FebsResponse febsResponse = new FebsResponse().message(message);
|
||||
FebsUtil.makeFailureResponse(httpServletResponse, febsResponse);
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.yida.data.auth.handler;
|
||||
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
import com.yida.data.common.core.utils.FebsUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
|
||||
import org.springframework.security.web.savedrequest.RequestCache;
|
||||
import org.springframework.security.web.savedrequest.SavedRequest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class FebsWebLoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
|
||||
|
||||
private final RequestCache requestCache = new HttpSessionRequestCache();
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
|
||||
SavedRequest savedRequest = requestCache.getRequest(request, response);
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session != null) {
|
||||
Object attribute = session.getAttribute("SPRING_SECURITY_SAVED_REQUEST");
|
||||
log.info("跳转到登录页的地址为: {}", attribute);
|
||||
}
|
||||
if (FebsUtil.isAjaxRequest(request)) {
|
||||
FebsResponse data = new FebsResponse();
|
||||
if (savedRequest == null) {
|
||||
FebsUtil.makeFailureResponse(response, data.message("请通过授权码模式跳转到该页面"));
|
||||
return;
|
||||
}
|
||||
data.data(savedRequest.getRedirectUrl());
|
||||
FebsUtil.makeSuccessResponse(response, data);
|
||||
} else {
|
||||
if (savedRequest == null) {
|
||||
super.onAuthenticationSuccess(request, response, authentication);
|
||||
return;
|
||||
}
|
||||
clearAuthenticationAttributes(request);
|
||||
getRedirectStrategy().sendRedirect(request, response, savedRequest.getRedirectUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.yida.data.auth.manager;
|
||||
|
||||
import cc.mrbird.febs.common.redis.service.RedisService;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.yida.data.auth.mapper.EduUserLogoMapper;
|
||||
import com.yida.data.auth.mapper.MenuMapper;
|
||||
import com.yida.data.auth.mapper.RoleMapper;
|
||||
import com.yida.data.auth.mapper.UserMapper;
|
||||
import com.yida.data.auth.mapper.UserMenuMapper;
|
||||
import com.yida.data.auth.mapper.UserRoleMapper;
|
||||
import com.yida.data.common.core.entity.constant.CachePrefixConstant;
|
||||
import com.yida.data.common.core.entity.constant.FebsConstant;
|
||||
import com.yida.data.common.core.entity.constant.StringConstant;
|
||||
import com.yida.data.common.core.entity.system.Dept;
|
||||
import com.yida.data.common.core.entity.system.EduUserLogo;
|
||||
import com.yida.data.common.core.entity.system.Menu;
|
||||
import com.yida.data.common.core.entity.system.Role;
|
||||
import com.yida.data.common.core.entity.system.SystemUser;
|
||||
import com.yida.data.common.core.entity.system.SystemUserMenu;
|
||||
import com.yida.data.common.core.entity.system.UserRole;
|
||||
import com.yida.data.common.service.CommonService;
|
||||
import com.yida.data.user.feign.RemoteTeacherService;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* 用户业务逻辑
|
||||
*
|
||||
* @author MrBird
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
|
||||
public class UserManager {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final EduUserLogoMapper eduUserLogoMapper;
|
||||
private final MenuMapper menuMapper;
|
||||
private final RoleMapper roleMapper;
|
||||
private final UserRoleMapper userRoleMapper;
|
||||
private final UserMenuMapper userMenuMapper;
|
||||
private final RemoteTeacherService remoteTeacherService;
|
||||
private final RedisService redisService;
|
||||
private final CommonService commonService;
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户信息
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 用户
|
||||
*/
|
||||
public SystemUser findByName(String username) {
|
||||
Object deptO = redisService.hget(CachePrefixConstant.USER_LOGIN_DEPT, username);
|
||||
SystemUser user = userMapper.findByName(username);
|
||||
if (user != null) {
|
||||
if (deptO != null) {
|
||||
Long deptId = Long.valueOf(deptO.toString());
|
||||
Dept dept = commonService.getDept(deptId);
|
||||
user.setDeptId(dept.getDeptId());
|
||||
user.setDeptName(dept.getDeptName());
|
||||
user.setDeptType(dept.getDeptType());
|
||||
}
|
||||
user.setUserLogo(
|
||||
eduUserLogoMapper.selectOne(Wrappers.<EduUserLogo>lambdaQuery().eq(EduUserLogo::getUserId, user.getUserId())));
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户权限串
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 权限
|
||||
*/
|
||||
public List<String> findUserPermissions(String username) {
|
||||
// 获取角色权限
|
||||
List<String> menus = menuMapper.findUserPermissions(username);
|
||||
// 获取用户权限
|
||||
List<SystemUserMenu> userPermissions = userMenuMapper.findUserPermissions(username);
|
||||
// 过滤
|
||||
if (CollUtil.isNotEmpty(userPermissions)) {
|
||||
menus.addAll(
|
||||
userPermissions.stream().filter(x -> x.getType() == 0).map(SystemUserMenu::getPerms).filter(StrUtil::isNotBlank)
|
||||
.collect(Collectors.toList()));
|
||||
List<String> excludePerms = userPermissions.stream().filter(x -> x.getType() == 1).map(SystemUserMenu::getPerms)
|
||||
.filter(StrUtil::isNotBlank).collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(excludePerms)) {
|
||||
menus = menus.stream().filter(x -> !excludePerms.contains(x)).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
// 只返回串
|
||||
return menus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册用户
|
||||
*
|
||||
* @param username username
|
||||
* @param password password
|
||||
* @return SystemUser SystemUser
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SystemUser registUser(String username, String password) {
|
||||
SystemUser systemUser = new SystemUser();
|
||||
systemUser.setUsername(username);
|
||||
systemUser.setPassword(password);
|
||||
systemUser.setStatus(SystemUser.STATUS_VALID);
|
||||
systemUser.setSex(SystemUser.SEX_UNKNOW);
|
||||
systemUser.setAvatar(SystemUser.DEFAULT_AVATAR);
|
||||
systemUser.setDescription("注册用户");
|
||||
userMapper.insert(systemUser);
|
||||
|
||||
UserRole userRole = new UserRole();
|
||||
userRole.setUserId(systemUser.getUserId());
|
||||
// 注册用户角色 ID
|
||||
userRole.setRoleId(FebsConstant.REGISTER_ROLE_ID);
|
||||
userRoleMapper.insert(userRole);
|
||||
return systemUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册用户
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public SystemUser registUser(SystemUser systemUser) {
|
||||
systemUser.setStatus(SystemUser.STATUS_VALID);
|
||||
userMapper.insert(systemUser);
|
||||
UserRole userRole = new UserRole();
|
||||
userRole.setUserId(systemUser.getUserId());
|
||||
if (systemUser.getRoleId() != null) {
|
||||
// 注册用户角色 ID
|
||||
userRole.setRoleId(Long.valueOf(systemUser.getRoleId()));
|
||||
userRoleMapper.insert(userRole);
|
||||
} else if (StrUtil.isNotBlank(systemUser.getRoleName())) {
|
||||
Role role = roleMapper.selectOne(Wrappers.<Role>lambdaQuery().eq(Role::getRoleName, systemUser.getRoleName()));
|
||||
userRole.setRoleId(role.getRoleId());
|
||||
userRoleMapper.insert(userRole);
|
||||
}
|
||||
return systemUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加角色
|
||||
*/
|
||||
public void addRole(Long userId, Long roleId) {
|
||||
UserRole userRole = new UserRole();
|
||||
userRole.setRoleId(roleId);
|
||||
userRole.setUserId(userId);
|
||||
userRoleMapper.insert(userRole);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询主角色code字符串
|
||||
*
|
||||
* @param mainDeptId 主部门id
|
||||
* @return java.lang.String
|
||||
* @author ZYJ
|
||||
* @date 2022/1/14 10:36
|
||||
*/
|
||||
public String findMainRole(Long mainDeptId) {
|
||||
// 查询主角色code
|
||||
List<String> rolePerms = userMapper.findMainRole(mainDeptId);
|
||||
return rolePerms.stream().filter(StringUtils::isNotBlank).distinct().collect(Collectors.joining(StringConstant.COMMA));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yida.data.common.core.entity.system.EduUserApp;
|
||||
|
||||
public interface EduUserAppMapper extends BaseMapper<EduUserApp> {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yida.data.common.core.entity.system.EduUserLogo;
|
||||
|
||||
public interface EduUserLogoMapper extends BaseMapper<EduUserLogo> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.yida.data.common.core.entity.system.Menu;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
public interface MenuMapper extends BaseMapper<Menu> {
|
||||
|
||||
/**
|
||||
* 获取用户权限集
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 权限集合
|
||||
*/
|
||||
List<String> findUserPermissions(String username);
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
import com.yida.data.common.core.entity.auth.OauthClientDetails;
|
||||
|
||||
/**
|
||||
* @author Yuuki
|
||||
*/
|
||||
public interface OauthClientDetailsMapper extends BaseMapper<OauthClientDetails> {
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yida.data.common.core.entity.system.Role;
|
||||
|
||||
public interface RoleMapper extends BaseMapper<Role> {
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
import com.yida.data.common.core.entity.system.UserConnection;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
public interface UserConnectionMapper extends BaseMapper<UserConnection> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yida.data.common.core.entity.system.SystemUser;
|
||||
import com.yida.data.common.core.entity.system.UserDataPermission;
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
public interface UserMapper extends BaseMapper<SystemUser> {
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 用户
|
||||
*/
|
||||
SystemUser findByName(String username);
|
||||
|
||||
/**
|
||||
* 获取用户数据权限
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return 数据权限
|
||||
*/
|
||||
List<UserDataPermission> findUserDataPermissions(Long userId);
|
||||
|
||||
/**
|
||||
* 查询用户
|
||||
*
|
||||
* @param deptId 部门
|
||||
* @param perms 角色perms
|
||||
* @return
|
||||
*/
|
||||
List<SystemUser> listUserByPerms(@Param("deptId") Long deptId,
|
||||
@Param("perms") String perms);
|
||||
|
||||
/**
|
||||
* 查询主角色code字符串
|
||||
*
|
||||
* @param mainDeptId 主部门id
|
||||
* @return java.util.List<java.lang.String>
|
||||
* @author ZYJ
|
||||
* @date 2022/1/14 13:24
|
||||
*/
|
||||
List<String> findMainRole(@Param("mainDeptId") Long mainDeptId);
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.yida.data.common.core.entity.system.Menu;
|
||||
import com.yida.data.common.core.entity.system.SystemUserMenu;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户权限dao曾
|
||||
*
|
||||
* @author ZYJ
|
||||
* @date 2021/11/8
|
||||
*/
|
||||
public interface UserMenuMapper extends BaseMapper<SystemUserMenu> {
|
||||
|
||||
/**
|
||||
* 通过用户名查询用户权限串
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return java.util.List<com.yida.data.common.core.entity.system.Menu>
|
||||
* @author ZYJ
|
||||
* @date 2021/11/8 15:54
|
||||
*/
|
||||
List<SystemUserMenu> findUserPermissions(String username);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.yida.data.auth.mapper;
|
||||
|
||||
import com.yida.data.common.core.entity.system.UserRole;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
public interface UserRoleMapper extends BaseMapper<UserRole> {
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package com.yida.data.auth.properties;
|
||||
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Data
|
||||
@SpringBootConfiguration
|
||||
@PropertySource(value = {"classpath:febs-auth.properties"})
|
||||
@ConfigurationProperties(prefix = "febs.auth")
|
||||
public class FebsAuthProperties {
|
||||
/**
|
||||
* 验证码配置
|
||||
*/
|
||||
private FebsValidateCodeProperties code = new FebsValidateCodeProperties();
|
||||
/**
|
||||
* JWT加签密钥
|
||||
*/
|
||||
private String jwtAccessKey;
|
||||
/**
|
||||
* 是否使用 JWT令牌
|
||||
*/
|
||||
private Boolean enableJwt;
|
||||
|
||||
/**
|
||||
* 社交登录所使用的 Client
|
||||
*/
|
||||
private String socialLoginClientId;
|
||||
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.yida.data.auth.properties;
|
||||
|
||||
import com.yida.data.common.core.entity.constant.ImageTypeConstant;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Data
|
||||
public class FebsValidateCodeProperties {
|
||||
|
||||
/**
|
||||
* 验证码有效时间,单位秒
|
||||
*/
|
||||
private Long time = 120L;
|
||||
/**
|
||||
* 验证码类型,可选值 png和 gif
|
||||
*/
|
||||
private String type = ImageTypeConstant.PNG;
|
||||
/**
|
||||
* 图片宽度,px
|
||||
*/
|
||||
private Integer width = 130;
|
||||
/**
|
||||
* 图片高度,px
|
||||
*/
|
||||
private Integer height = 48;
|
||||
/**
|
||||
* 验证码位数
|
||||
*/
|
||||
private Integer length = 4;
|
||||
/**
|
||||
* 验证码值的类型
|
||||
* 1. 数字加字母
|
||||
* 2. 纯数字
|
||||
* 3. 纯字母
|
||||
*/
|
||||
private Integer charType = 2;
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.yida.data.auth.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import com.yida.data.common.core.entity.QueryRequest;
|
||||
import com.yida.data.common.core.entity.auth.OauthClientDetails;
|
||||
import com.yida.data.common.core.exception.FebsException;
|
||||
|
||||
/**
|
||||
* @author Yuuki
|
||||
*/
|
||||
public interface OauthClientDetailsService extends IService<OauthClientDetails> {
|
||||
|
||||
/**
|
||||
* 查询(分页)
|
||||
*
|
||||
* @param request QueryRequest
|
||||
* @param oauthClientDetails oauthClientDetails
|
||||
* @return IPage<OauthClientDetails>
|
||||
*/
|
||||
IPage<OauthClientDetails> findOauthClientDetails(QueryRequest request, OauthClientDetails oauthClientDetails);
|
||||
|
||||
/**
|
||||
* 根据主键查询
|
||||
*
|
||||
* @param clientId clientId
|
||||
* @return OauthClientDetails
|
||||
*/
|
||||
OauthClientDetails findById(String clientId);
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param oauthClientDetails oauthClientDetails
|
||||
* @throws FebsException FebsException
|
||||
*/
|
||||
void createOauthClientDetails(OauthClientDetails oauthClientDetails) throws FebsException;
|
||||
|
||||
/**
|
||||
* 修改
|
||||
*
|
||||
* @param oauthClientDetails oauthClientDetails
|
||||
*/
|
||||
void updateOauthClientDetails(OauthClientDetails oauthClientDetails);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param clientIds clientIds
|
||||
*/
|
||||
void deleteOauthClientDetails(String clientIds);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.yida.data.auth.service;
|
||||
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
|
||||
public interface SecurityService {
|
||||
|
||||
/**
|
||||
* 得到学校管理员账号的token
|
||||
*
|
||||
* @param schoolId
|
||||
* @return
|
||||
*/
|
||||
OAuth2AccessToken getSchoolToken(Long schoolId);
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
package com.yida.data.auth.service;
|
||||
|
||||
import com.yida.data.auth.entity.BindUser;
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
import com.yida.data.common.core.entity.system.UserConnection;
|
||||
import com.yida.data.common.core.exception.FebsException;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
public interface SocialLoginService {
|
||||
|
||||
/**
|
||||
* 解析第三方登录请求
|
||||
*
|
||||
* @param oauthType 第三方平台类型
|
||||
* @return AuthRequest
|
||||
* @throws FebsException 异常
|
||||
*/
|
||||
AuthRequest renderAuth(String oauthType) throws FebsException;
|
||||
|
||||
/**
|
||||
* 处理第三方登录(绑定页面)
|
||||
*
|
||||
* @param oauthType 第三方平台类型
|
||||
* @param callback 回调
|
||||
* @return FebsResponse
|
||||
* @throws FebsException 异常
|
||||
*/
|
||||
FebsResponse resolveBind(String oauthType, AuthCallback callback) throws FebsException;
|
||||
|
||||
/**
|
||||
* 处理第三方登录(登录页面)
|
||||
*
|
||||
* @param oauthType 第三方平台类型
|
||||
* @param callback 回调
|
||||
* @return FebsResponse
|
||||
* @throws FebsException 异常
|
||||
*/
|
||||
FebsResponse resolveLogin(String oauthType, AuthCallback callback) throws FebsException;
|
||||
|
||||
/**
|
||||
* 绑定并登录
|
||||
*
|
||||
* @param bindUser 绑定用户
|
||||
* @param authUser 第三方平台对象
|
||||
* @return OAuth2AccessToken 令牌对象
|
||||
* @throws FebsException 异常
|
||||
*/
|
||||
OAuth2AccessToken bindLogin(BindUser bindUser, AuthUser authUser) throws FebsException;
|
||||
|
||||
/**
|
||||
* 注册并登录
|
||||
*
|
||||
* @param registUser 注册用户
|
||||
* @param authUser 第三方平台对象
|
||||
* @return OAuth2AccessToken 令牌对象
|
||||
* @throws FebsException 异常
|
||||
*/
|
||||
OAuth2AccessToken signLogin(BindUser registUser, AuthUser authUser) throws FebsException;
|
||||
|
||||
/**
|
||||
* 绑定
|
||||
*
|
||||
* @param bindUser 绑定对象
|
||||
* @param authUser 第三方平台对象
|
||||
* @throws FebsException 异常
|
||||
*/
|
||||
void bind(BindUser bindUser, AuthUser authUser) throws FebsException;
|
||||
|
||||
/**
|
||||
* 解绑
|
||||
*
|
||||
* @param bindUser 绑定对象
|
||||
* @param oauthType 第三方平台对象
|
||||
* @throws FebsException 异常
|
||||
*/
|
||||
void unbind(BindUser bindUser, String oauthType) throws FebsException;
|
||||
|
||||
/**
|
||||
* 根据用户名获取绑定关系
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 绑定关系集合
|
||||
*/
|
||||
List<UserConnection> findUserConnections(String username);
|
||||
|
||||
/**
|
||||
* 企业微信用户登录/注册登录
|
||||
*/
|
||||
Map<String, Object> qywxLogin(String code, String state, String corpId, Integer type);
|
||||
|
||||
/**
|
||||
* app用户登录
|
||||
*/
|
||||
Map<String, Object> appLogin(String areaId, Long schoolId, String mobile, String userId, Integer type);
|
||||
|
||||
Map<String, Object> wxpublicLogin(String code, String appId, Integer type, Long schoolId, String mobile);
|
||||
|
||||
Map<String, Object> h5Login(Long schoolId, String mobile, Integer type);
|
||||
|
||||
/**
|
||||
* 检查openId状态
|
||||
*
|
||||
* @param code 微信公众号授权code
|
||||
* @param deptId 学校id
|
||||
* @return java.util.Map<java.lang.String, java.lang.Object>
|
||||
* @author ZYJ
|
||||
* @date 2023/6/2 10:31
|
||||
*/
|
||||
Map<String, Object> checkOpenId(String code, Long deptId);
|
||||
|
||||
/**
|
||||
* 迎新功能微信公众号登录
|
||||
*
|
||||
* @param openId 微信openId
|
||||
* @param deptId 学校id
|
||||
* @return java.util.Map<java.lang.String, java.lang.Object>
|
||||
* @author ZYJ
|
||||
* @date 2023/5/18 11:09
|
||||
*/
|
||||
Map<String, Object> wxPublicLogin(String openId, Long deptId);
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.yida.data.auth.service;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.yida.data.common.core.entity.system.UserConnection;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
public interface UserConnectionService extends IService<UserConnection> {
|
||||
|
||||
/**
|
||||
* 根据条件查询关联关系
|
||||
*
|
||||
* @param providerName 平台名称
|
||||
* @param providerUserId 平台用户ID
|
||||
* @return 关联关系
|
||||
*/
|
||||
UserConnection selectByCondition(String providerName, String providerUserId);
|
||||
|
||||
/**
|
||||
* 根据条件查询关联关系
|
||||
*
|
||||
* @param username 用户名
|
||||
* @return 关联关系
|
||||
*/
|
||||
List<UserConnection> selectByCondition(String username);
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*
|
||||
* @param userConnection userConnection
|
||||
*/
|
||||
void createUserConnection(UserConnection userConnection);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*
|
||||
* @param username username 用户名
|
||||
* @param providerName providerName 平台名称
|
||||
*/
|
||||
void deleteByCondition(String username, String providerName);
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.yida.data.auth.service;
|
||||
|
||||
import com.yida.data.common.core.exception.ValidateCodeException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
public interface ValidateCodeService {
|
||||
|
||||
/**
|
||||
* 生成验证码
|
||||
*
|
||||
* @param request HttpServletRequest
|
||||
* @param response HttpServletResponse
|
||||
* @throws IOException IO异常
|
||||
* @throws ValidateCodeException 验证码异常
|
||||
*/
|
||||
void create(HttpServletRequest request, HttpServletResponse response) throws IOException, ValidateCodeException;
|
||||
|
||||
/**
|
||||
* 校验验证码
|
||||
*
|
||||
* @param key 前端上送 key
|
||||
* @param value 前端上送待校验值
|
||||
* @throws ValidateCodeException 验证码异常
|
||||
*/
|
||||
void check(String key, String value) throws ValidateCodeException;
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package com.yida.data.auth.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import com.yida.data.auth.manager.UserManager;
|
||||
import cc.mrbird.febs.common.redis.service.RedisService;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.yida.data.common.core.entity.FebsAuthUser;
|
||||
import com.yida.data.common.core.entity.constant.FebsConstant;
|
||||
import com.yida.data.common.core.entity.constant.ParamsConstant;
|
||||
import com.yida.data.common.core.entity.constant.SocialConstant;
|
||||
import com.yida.data.common.core.entity.constant.StringConstant;
|
||||
import com.yida.data.common.core.entity.system.SystemUser;
|
||||
import com.yida.data.common.core.utils.FebsUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class FebsUserDetailServiceImpl implements UserDetailsService {
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final UserManager userManager;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
HttpServletRequest httpServletRequest = FebsUtil.getHttpServletRequest();
|
||||
SystemUser systemUser = userManager.findByName(username);
|
||||
if (systemUser != null) {
|
||||
List<String> permissions = userManager.findUserPermissions(systemUser.getUsername());
|
||||
boolean notLocked = false;
|
||||
if (StringUtils.equals(SystemUser.STATUS_VALID, systemUser.getStatus())) {
|
||||
notLocked = true;
|
||||
}
|
||||
String password = systemUser.getPassword();
|
||||
String loginType = (String) httpServletRequest.getAttribute(ParamsConstant.LOGIN_TYPE);
|
||||
if (StringUtils.equals(loginType, SocialConstant.SOCIAL_LOGIN)) {
|
||||
password = passwordEncoder.encode(SocialConstant.getSocialLoginPassword());
|
||||
}
|
||||
|
||||
List<GrantedAuthority> grantedAuthorities = AuthorityUtils.NO_AUTHORITIES;
|
||||
// 设置角色权限
|
||||
if (StringUtils.isNotBlank(systemUser.getRolePerms())) {
|
||||
List<String> collect = Arrays.stream(systemUser.getRolePerms().split(StringConstant.COMMA))
|
||||
.map(s -> FebsConstant.SECURITY_ROLE_PREFIX + s)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
if (CollectionUtils.isNotEmpty(collect)) {
|
||||
grantedAuthorities = AuthorityUtils
|
||||
.commaSeparatedStringToAuthorityList(String.join(StringConstant.COMMA, collect));
|
||||
}
|
||||
}
|
||||
// 设置菜单权限
|
||||
if (CollUtil.isNotEmpty(permissions)) {
|
||||
grantedAuthorities.addAll(AuthorityUtils.createAuthorityList(permissions.toArray(new String[0])));
|
||||
}
|
||||
// 查询主角色信息
|
||||
if (Objects.nonNull(systemUser.getMainDeptId())) {
|
||||
String role = this.userManager.findMainRole(systemUser.getMainDeptId());
|
||||
systemUser.setMainRolePerms(role);
|
||||
}
|
||||
|
||||
//查询登录所属部门:学校对应的
|
||||
log.info("登陆用户信息sysUser: {}", systemUser);
|
||||
log.info("登陆权限数据permission: {}", grantedAuthorities);
|
||||
log.info("登陆主角色数据mainRole: {}", systemUser.getMainRolePerms());
|
||||
|
||||
FebsAuthUser authUser = new FebsAuthUser(systemUser.getUsername(), password, true, true, true, notLocked,
|
||||
grantedAuthorities);
|
||||
|
||||
BeanUtils.copyProperties(systemUser, authUser);
|
||||
return authUser;
|
||||
} else {
|
||||
throw new UsernameNotFoundException("");
|
||||
}
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
package com.yida.data.auth.service.impl;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.yida.data.auth.mapper.OauthClientDetailsMapper;
|
||||
import com.yida.data.auth.service.OauthClientDetailsService;
|
||||
import com.yida.data.common.core.entity.QueryRequest;
|
||||
import com.yida.data.common.core.entity.auth.OauthClientDetails;
|
||||
import com.yida.data.common.core.entity.constant.StringConstant;
|
||||
import com.yida.data.common.core.exception.FebsException;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author Yuuki
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
|
||||
public class OauthClientDetailsServiceImpl extends ServiceImpl<OauthClientDetailsMapper, OauthClientDetails> implements OauthClientDetailsService {
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final RedisClientDetailsService redisClientDetailsService;
|
||||
|
||||
@Override
|
||||
public IPage<OauthClientDetails> findOauthClientDetails(QueryRequest request, OauthClientDetails oauthClientDetails) {
|
||||
LambdaQueryWrapper<OauthClientDetails> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.isNotBlank(oauthClientDetails.getClientId())) {
|
||||
queryWrapper.eq(OauthClientDetails::getClientId, oauthClientDetails.getClientId());
|
||||
}
|
||||
Page<OauthClientDetails> page = new Page<>(request.getPageNum(), request.getPageSize());
|
||||
IPage<OauthClientDetails> result = this.page(page, queryWrapper);
|
||||
|
||||
List<OauthClientDetails> records = new ArrayList<>();
|
||||
result.getRecords().forEach(o -> {
|
||||
o.setOriginSecret(null);
|
||||
o.setClientSecret(null);
|
||||
records.add(o);
|
||||
});
|
||||
result.setRecords(records);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OauthClientDetails findById(String clientId) {
|
||||
return this.baseMapper.selectById(clientId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void createOauthClientDetails(OauthClientDetails oauthClientDetails) throws FebsException {
|
||||
OauthClientDetails byId = this.findById(oauthClientDetails.getClientId());
|
||||
if (byId != null) {
|
||||
throw new FebsException("该Client已存在");
|
||||
}
|
||||
oauthClientDetails.setOriginSecret(oauthClientDetails.getClientSecret());
|
||||
oauthClientDetails.setClientSecret(passwordEncoder.encode(oauthClientDetails.getClientSecret()));
|
||||
boolean saved = this.save(oauthClientDetails);
|
||||
if (saved) {
|
||||
log.info("缓存Client -> {}", oauthClientDetails);
|
||||
this.redisClientDetailsService.loadClientByClientId(oauthClientDetails.getClientId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateOauthClientDetails(OauthClientDetails oauthClientDetails) {
|
||||
String clientId = oauthClientDetails.getClientId();
|
||||
|
||||
LambdaQueryWrapper<OauthClientDetails> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(OauthClientDetails::getClientId, oauthClientDetails.getClientId());
|
||||
|
||||
oauthClientDetails.setClientId(null);
|
||||
oauthClientDetails.setClientSecret(null);
|
||||
boolean updated = this.update(oauthClientDetails, queryWrapper);
|
||||
if (updated) {
|
||||
log.info("更新Client -> {}", oauthClientDetails);
|
||||
this.redisClientDetailsService.removeRedisCache(clientId);
|
||||
this.redisClientDetailsService.loadClientByClientId(clientId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteOauthClientDetails(String clientIds) {
|
||||
Object[] clientIdArray = StringUtils.splitByWholeSeparatorPreserveAllTokens(clientIds, StringConstant.COMMA);
|
||||
LambdaQueryWrapper<OauthClientDetails> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(OauthClientDetails::getClientId, clientIdArray);
|
||||
boolean removed = this.remove(queryWrapper);
|
||||
if (removed) {
|
||||
log.info("删除ClientId为({})的Client", clientIds);
|
||||
Arrays.stream(clientIdArray).forEach(c -> this.redisClientDetailsService.removeRedisCache(String.valueOf(c)));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package com.yida.data.auth.service.impl;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.SerializationUtils;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.code.RandomValueAuthorizationCodeServices;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 授权码保存到Redis,以确保认证服务器集群的一致性
|
||||
*
|
||||
* @author MrBird
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class RedisAuthenticationCodeService extends RandomValueAuthorizationCodeServices {
|
||||
|
||||
|
||||
private static final String AUTH_CODE_KEY = "auth_code";
|
||||
private final RedisConnectionFactory connectionFactory;
|
||||
|
||||
public RedisAuthenticationCodeService(RedisConnectionFactory connectionFactory) {
|
||||
Assert.notNull(connectionFactory, "RedisConnectionFactory required");
|
||||
this.connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OAuth2Authentication remove(String code) {
|
||||
RedisConnection conn = getConnection();
|
||||
try {
|
||||
byte[] bytes = conn.hGet(AUTH_CODE_KEY.getBytes(StandardCharsets.UTF_8), code.getBytes(StandardCharsets.UTF_8));
|
||||
if (bytes == null || ArrayUtils.isEmpty(bytes)) {
|
||||
return null;
|
||||
}
|
||||
OAuth2Authentication authentication = SerializationUtils.deserialize(bytes);
|
||||
if (null != authentication) {
|
||||
conn.hDel(AUTH_CODE_KEY.getBytes(StandardCharsets.UTF_8), code.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
return authentication;
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
} finally {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void store(String code, OAuth2Authentication authentication) {
|
||||
RedisConnection conn = getConnection();
|
||||
try {
|
||||
conn.hSet(AUTH_CODE_KEY.getBytes(StandardCharsets.UTF_8), code.getBytes(StandardCharsets.UTF_8),
|
||||
SerializationUtils.serialize(authentication));
|
||||
log.info("保存authentication code: {}至redis", code);
|
||||
} catch (Exception e) {
|
||||
log.error("保存authentication code至redis失败", e);
|
||||
} finally {
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
|
||||
private RedisConnection getConnection() {
|
||||
return connectionFactory.getConnection();
|
||||
}
|
||||
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
package com.yida.data.auth.service.impl;
|
||||
|
||||
import cc.mrbird.febs.common.redis.service.RedisService;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidClientException;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.client.BaseClientDetails;
|
||||
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Yuuki
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class RedisClientDetailsService extends JdbcClientDetailsService {
|
||||
/**
|
||||
* 缓存 client的 redis key,这里是 hash结构存储
|
||||
*/
|
||||
private static final String CACHE_CLIENT_KEY = "client_details";
|
||||
|
||||
private final RedisService redisService;
|
||||
|
||||
public RedisClientDetailsService(DataSource dataSource, RedisService redisService) {
|
||||
super(dataSource);
|
||||
this.redisService = redisService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException {
|
||||
ClientDetails clientDetails = null;
|
||||
String value = (String) redisService.hget(CACHE_CLIENT_KEY, clientId);
|
||||
if (StringUtils.isBlank(value)) {
|
||||
clientDetails = cacheAndGetClient(clientId);
|
||||
} else {
|
||||
clientDetails = JSONObject.parseObject(value, BaseClientDetails.class);
|
||||
}
|
||||
|
||||
return clientDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存 client并返回 client
|
||||
*
|
||||
* @param clientId clientId
|
||||
*/
|
||||
public ClientDetails cacheAndGetClient(String clientId) {
|
||||
ClientDetails clientDetails = null;
|
||||
clientDetails = super.loadClientByClientId(clientId);
|
||||
if (clientDetails != null) {
|
||||
BaseClientDetails baseClientDetails = (BaseClientDetails) clientDetails;
|
||||
Set<String> autoApproveScopes = baseClientDetails.getAutoApproveScopes();
|
||||
if (CollectionUtils.isNotEmpty(autoApproveScopes)) {
|
||||
baseClientDetails.setAutoApproveScopes(
|
||||
autoApproveScopes.stream().map(this::convert).collect(Collectors.toSet())
|
||||
);
|
||||
}
|
||||
redisService.hset(CACHE_CLIENT_KEY, clientId, JSONObject.toJSONString(baseClientDetails));
|
||||
}
|
||||
return clientDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 redis缓存
|
||||
*
|
||||
* @param clientId clientId
|
||||
*/
|
||||
public void removeRedisCache(String clientId) {
|
||||
redisService.hdel(CACHE_CLIENT_KEY, clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 oauth_client_details全表刷入 redis
|
||||
*/
|
||||
public void loadAllClientToCache() {
|
||||
if (redisService.hasKey(CACHE_CLIENT_KEY)) {
|
||||
return;
|
||||
}
|
||||
log.info("将oauth_client_details全表刷入redis");
|
||||
|
||||
List<ClientDetails> list = super.listClientDetails();
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
log.error("oauth_client_details表数据为空,请检查");
|
||||
return;
|
||||
}
|
||||
list.forEach(client -> redisService.hset(CACHE_CLIENT_KEY, client.getClientId(), JSONObject.toJSONString(client)));
|
||||
}
|
||||
|
||||
private String convert(String value) {
|
||||
final String logicTrue = "1";
|
||||
return logicTrue.equals(value) ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.yida.data.auth.service.impl;
|
||||
|
||||
import com.yida.data.common.core.entity.system.SystemUser;
|
||||
import com.yida.data.common.core.entity.system.enums.RoleEnum;
|
||||
import com.yida.data.common.core.utils.Asserts;
|
||||
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.yida.data.auth.mapper.UserMapper;
|
||||
import com.yida.data.auth.service.SecurityService;
|
||||
import com.yida.data.auth.util.SecurityUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityServiceImpl implements SecurityService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final SecurityUtil securityUtil;
|
||||
|
||||
@Override
|
||||
public OAuth2AccessToken getSchoolToken(Long schoolId) {
|
||||
List<SystemUser> userList = userMapper.listUserByPerms(schoolId, RoleEnum.ROLE_SCHOOL_PRINCIPAL.getValue());
|
||||
Asserts.isTrue(CollUtil.isNotEmpty(userList), "该学校无学校负责人,请创建后重试");
|
||||
SystemUser schoolUser = userList.get(0);
|
||||
return securityUtil.getOauth2AccessToken(schoolUser);
|
||||
}
|
||||
}
|
||||
+622
@@ -0,0 +1,622 @@
|
||||
package com.yida.data.auth.service.impl;
|
||||
|
||||
import cc.mrbird.febs.common.redis.service.RedisService;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.xkcoding.justauth.AuthRequestFactory;
|
||||
import com.yida.data.auth.entity.BindUser;
|
||||
import com.yida.data.auth.manager.UserManager;
|
||||
import com.yida.data.auth.mapper.RoleMapper;
|
||||
import com.yida.data.auth.properties.FebsAuthProperties;
|
||||
import com.yida.data.auth.service.SocialLoginService;
|
||||
import com.yida.data.auth.service.UserConnectionService;
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
import com.yida.data.common.core.entity.constant.*;
|
||||
import com.yida.data.common.core.entity.smart.EduSmartWelcomeGuideRosterRelation;
|
||||
import com.yida.data.common.core.entity.smart.EduSmartWelcomeGuideStep;
|
||||
import com.yida.data.common.core.entity.system.*;
|
||||
import com.yida.data.common.core.entity.user.EduStaff;
|
||||
import com.yida.data.common.core.enums.RoleName;
|
||||
import com.yida.data.common.core.exception.FebsException;
|
||||
import com.yida.data.common.core.utils.Asserts;
|
||||
import com.yida.data.common.core.utils.FebsUtil;
|
||||
import com.yida.data.common.core.utils.WxPublicUtil;
|
||||
import com.yida.data.common.core.utils.WxUtil;
|
||||
import com.yida.data.common.service.CommonService;
|
||||
import com.yida.data.school.feign.smart.RemoteSmartWelcomeService;
|
||||
import com.yida.data.system.feign.RemoteDeptService;
|
||||
import com.yida.data.system.feign.RemoteRoleService;
|
||||
import com.yida.data.system.feign.RemoteUserService;
|
||||
import com.yida.data.user.feign.RemoteStaffService;
|
||||
import com.yida.data.user.feign.RemoteStudentApplyService;
|
||||
import com.yida.data.user.feign.RemoteStudentService;
|
||||
import com.yida.data.user.feign.RemoteTeacherService;
|
||||
import com.yida.data.user.vo.ParentInfoVO;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.config.AuthSource;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthResponse;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.TokenRequest;
|
||||
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class SocialLoginServiceImpl implements SocialLoginService {
|
||||
|
||||
private static final String USERNAME = "username";
|
||||
private static final String PASSWORD = "password";
|
||||
private static final String NOT_BIND = "not_bind";
|
||||
private static final String SOCIAL_LOGIN_SUCCESS = "social_login_success";
|
||||
|
||||
private final UserManager userManager;
|
||||
private final RoleMapper roleMapper;
|
||||
private final AuthRequestFactory factory;
|
||||
private final FebsAuthProperties properties;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final UserConnectionService userConnectionService;
|
||||
private final ResourceOwnerPasswordTokenGranter granter;
|
||||
private final RedisClientDetailsService redisClientDetailsService;
|
||||
|
||||
private final RemoteStaffService remoteStaffService;
|
||||
private final RemoteStudentService remoteStudentService;
|
||||
private final RemoteTeacherService remoteTeacherService;
|
||||
private final RemoteSmartWelcomeService remoteSmartWelcomeService;
|
||||
|
||||
private final WxUtil wxUtil;
|
||||
private final WxPublicUtil wxPublicUtil;
|
||||
private final RedisService redisService;
|
||||
private final CommonService commonService;
|
||||
|
||||
@Override
|
||||
public AuthRequest renderAuth(String oauthType) throws FebsException {
|
||||
return factory.get(getAuthSource(oauthType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FebsResponse resolveBind(String oauthType, AuthCallback callback) throws FebsException {
|
||||
FebsResponse febsResponse = new FebsResponse();
|
||||
AuthRequest authRequest = factory.get(getAuthSource(oauthType));
|
||||
AuthResponse<?> response = authRequest.login(resolveAuthCallback(callback));
|
||||
if (response.ok()) {
|
||||
febsResponse.data(response.getData());
|
||||
} else {
|
||||
throw new FebsException(String.format("第三方登录失败,%s", response.getMsg()));
|
||||
}
|
||||
return febsResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FebsResponse resolveLogin(String oauthType, AuthCallback callback) throws FebsException {
|
||||
FebsResponse febsResponse = new FebsResponse();
|
||||
AuthRequest authRequest = factory.get(getAuthSource(oauthType));
|
||||
AuthResponse<?> response = authRequest.login(resolveAuthCallback(callback));
|
||||
if (response.ok()) {
|
||||
AuthUser authUser = (AuthUser) response.getData();
|
||||
UserConnection userConnection = userConnectionService
|
||||
.selectByCondition(authUser.getSource().toString(), authUser.getUuid());
|
||||
if (userConnection == null) {
|
||||
febsResponse.message(NOT_BIND).data(authUser);
|
||||
} else {
|
||||
SystemUser user = userManager.findByName(userConnection.getUserName());
|
||||
if (user == null) {
|
||||
throw new FebsException("系统中未找到与第三方账号对应的账户");
|
||||
}
|
||||
OAuth2AccessToken oAuth2AccessToken = getOauth2AccessToken(user);
|
||||
febsResponse.message(SOCIAL_LOGIN_SUCCESS).data(oAuth2AccessToken);
|
||||
febsResponse.put(USERNAME, user.getUsername());
|
||||
}
|
||||
} else {
|
||||
throw new FebsException(String.format("第三方登录失败,%s", response.getMsg()));
|
||||
}
|
||||
return febsResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessToken bindLogin(BindUser bindUser, AuthUser authUser) throws FebsException {
|
||||
SystemUser systemUser = userManager.findByName(bindUser.getBindUsername());
|
||||
if (systemUser == null || !passwordEncoder.matches(bindUser.getBindPassword(), systemUser.getPassword())) {
|
||||
throw new FebsException("绑定系统账号失败,用户名或密码错误!");
|
||||
}
|
||||
this.createConnection(systemUser, authUser);
|
||||
return this.getOauth2AccessToken(systemUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessToken signLogin(BindUser registUser, AuthUser authUser) throws FebsException {
|
||||
SystemUser user = this.userManager.findByName(registUser.getBindUsername());
|
||||
if (user != null) {
|
||||
throw new FebsException("该用户名已存在!");
|
||||
}
|
||||
String encryptPassword = passwordEncoder.encode(registUser.getBindPassword());
|
||||
SystemUser systemUser = this.userManager.registUser(registUser.getBindUsername(), encryptPassword);
|
||||
this.createConnection(systemUser, authUser);
|
||||
return this.getOauth2AccessToken(systemUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(BindUser bindUser, AuthUser authUser) throws FebsException {
|
||||
String username = bindUser.getBindUsername();
|
||||
if (isCurrentUser(username)) {
|
||||
UserConnection userConnection = userConnectionService
|
||||
.selectByCondition(authUser.getSource().toString(), authUser.getUuid());
|
||||
if (userConnection != null) {
|
||||
throw new FebsException("绑定失败,该第三方账号已绑定" + userConnection.getUserName() + "系统账户");
|
||||
}
|
||||
SystemUser systemUser = new SystemUser();
|
||||
systemUser.setUsername(username);
|
||||
this.createConnection(systemUser, authUser);
|
||||
} else {
|
||||
throw new FebsException("绑定失败,您无权绑定别人的账号");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind(BindUser bindUser, String oauthType) throws FebsException {
|
||||
String username = bindUser.getBindUsername();
|
||||
if (isCurrentUser(username)) {
|
||||
this.userConnectionService.deleteByCondition(username, oauthType);
|
||||
} else {
|
||||
throw new FebsException("解绑失败,您无权解绑别人的账号");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConnection> findUserConnections(String username) {
|
||||
return this.userConnectionService.selectByCondition(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> qywxLogin(String code, String state, String corpId, Integer type) {
|
||||
log.info("code:{},state:{},corpid:{}", code, state, corpId);
|
||||
Dept school = commonService.getSchoolByCorpId(corpId);
|
||||
// 获取secret
|
||||
EduApp eduApp = commonService.getAppByCodeAndSchool(state, corpId, null);
|
||||
log.info("corpId:{},app:{}", corpId, eduApp != null ? eduApp.toString() : "null");
|
||||
if (eduApp == null || StrUtil.isBlank(eduApp.getWxSecret())) {
|
||||
throw new FebsException("该应用暂未登记");
|
||||
}
|
||||
// 获取access token
|
||||
String accessToken = wxUtil.getAccessToken(corpId, eduApp.getWxSecret());
|
||||
// 查询用户信息
|
||||
JSONObject user = wxUtil.getUserInfo(accessToken, code);
|
||||
log.info("user:[{}]", user);
|
||||
// 分别为 企业用户 家长
|
||||
ParentInfoVO parent = null;
|
||||
EduStaff teacher = null;
|
||||
// 家长和教师标识
|
||||
Object userId = user.get("UserId");
|
||||
Object parentUserid = user.get("parent_userid");
|
||||
if (type == 0) {
|
||||
if (userId != null) {
|
||||
teacher = remoteStaffService
|
||||
.getStaffByWxOrMobileOrOpenId(userId.toString(), null, null, school.getDeptId())
|
||||
.getData();
|
||||
} else if (parentUserid != null) {
|
||||
// 通过家长信息转化为职工信息
|
||||
parent = remoteStudentService.getParentWithStudent(null, parentUserid.toString(),
|
||||
school.getDeptId()).getData();
|
||||
if (parent != null) {
|
||||
teacher = remoteStaffService
|
||||
.getStaffByWxOrMobileOrOpenId(null, parent.getMobile(), null, school.getDeptId())
|
||||
.getData();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (parentUserid != null) {
|
||||
parent = remoteStudentService.getParentWithStudent(null, parentUserid.toString(),
|
||||
school.getDeptId()).getData();
|
||||
} else if (userId != null) {
|
||||
// 通过职工信息转化为家长信息
|
||||
teacher = remoteStaffService
|
||||
.getStaffByWxOrMobileOrOpenId(userId.toString(), null, null, school.getDeptId())
|
||||
.getData();
|
||||
if (teacher != null) {
|
||||
parent = remoteStudentService.getParentWithStudent(teacher.getMobile(), null,
|
||||
school.getDeptId()).getData();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (teacher == null && parent == null) {
|
||||
throw new FebsException("该用户暂未注册");
|
||||
}
|
||||
// 教师用户查询是否绑定手机号(家长必定有手机号)
|
||||
if (type == 0 && StrUtil.isBlank(teacher.getMobile())) {
|
||||
throw new FebsException("请绑定企业微信手机号");
|
||||
}
|
||||
redisService.hset(CachePrefixConstant.USER_LOGIN_DEPT, type == 0 ? teacher.getMobile() :
|
||||
parent.getMobile(), school.getDeptId());
|
||||
// 查询系统用户
|
||||
SystemUser systemUser = userManager.findByName(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
// 系统用户不存在 进行注册
|
||||
if (systemUser == null) {
|
||||
systemUser = new SystemUser();
|
||||
systemUser.setNickname(type == 0 ? teacher.getName() : parent.getMobile());
|
||||
systemUser.setUsername(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
systemUser.setPassword(passwordEncoder.encode(SystemUser.DEFAULT_PASSWORD));
|
||||
systemUser.setSex(type == 0 ? teacher.getSex() : "2");
|
||||
systemUser.setAvatar(type == 0 ? teacher.getAvatar() : SystemUser.DEFAULT_AVATAR);
|
||||
systemUser.setMobile(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
systemUser.setUserOrigin(0);
|
||||
systemUser.setDeptId(school.getDeptId());
|
||||
systemUser.setRoleName(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName());
|
||||
systemUser.setUserType(type == 0 ? 1 : 0);
|
||||
// systemUser = remoteUserService.addUser(systemUser).getData();
|
||||
userManager.registUser(systemUser);
|
||||
} else if (!systemUser.getRoleName().contains(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName())) {
|
||||
Role role = roleMapper.selectOne(Wrappers.<Role>lambdaQuery()
|
||||
.eq(Role::getRoleName, type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName()));
|
||||
userManager.addRole(systemUser.getUserId(), role.getRoleId());
|
||||
systemUser.setRoleId(systemUser.getRoleId() + "," + role.getRoleId());
|
||||
systemUser.setRoleName(systemUser.getRoleName() + "," + role.getRoleName());
|
||||
}
|
||||
// 登录返回token和用户信息
|
||||
Map<String, Object> res = new HashMap<>();
|
||||
res.put("token", getOauth2AccessToken(systemUser));
|
||||
systemUser.setPassword(null);
|
||||
systemUser.setIdentityId(type == 0 ? teacher.getId() : parent.getParentId());
|
||||
res.put("user", systemUser);
|
||||
res.put("identity", type == 0 ? teacher : parent);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> appLogin(String areaId, Long schoolId, String mobile, String userId,
|
||||
Integer type) {
|
||||
Dept school = commonService.getDept(schoolId);
|
||||
Asserts.isNotNull(school, "该学校不存在");
|
||||
// 分别为 企业用户 家长
|
||||
ParentInfoVO parent = null;
|
||||
EduStaff teacher = null;
|
||||
// 家长和教师标识
|
||||
if (type == 0) {
|
||||
teacher = remoteStaffService.getStaffByWxOrMobileOrOpenId(null, mobile, null, school.getDeptId()).getData();
|
||||
} else {
|
||||
parent = remoteStudentService.getParentWithStudent(mobile, null, school.getDeptId()).getData();
|
||||
}
|
||||
if (teacher == null && parent == null) {
|
||||
throw new FebsException("该用户未注册");
|
||||
}
|
||||
redisService.hset(CachePrefixConstant.USER_LOGIN_DEPT, type == 0 ? teacher.getMobile() :
|
||||
parent.getMobile(), school.getDeptId());
|
||||
// 查询系统用户
|
||||
SystemUser systemUser = userManager.findByName(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
// 系统用户不存在 进行注册
|
||||
if (systemUser == null) {
|
||||
// Role role = remoteRoleService.getRoleByNameNoPermission(type == 0 ? "教师" : "家长").getData();
|
||||
systemUser = new SystemUser();
|
||||
systemUser.setNickname(type == 0 ? teacher.getName() : parent.getMobile());
|
||||
systemUser.setUsername(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
systemUser.setPassword(passwordEncoder.encode(SystemUser.DEFAULT_PASSWORD));
|
||||
systemUser.setSex(type == 0 ? teacher.getSex() : "2");
|
||||
systemUser.setAvatar(type == 0 ? teacher.getAvatar() : SystemUser.DEFAULT_AVATAR);
|
||||
systemUser.setMobile(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
systemUser.setUserOrigin(0);
|
||||
systemUser.setDeptId(type == 0 ? teacher.getSchoolId() : schoolId);
|
||||
systemUser.setRoleName(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName());
|
||||
systemUser.setUserType(type == 0 ? 1 : 0);
|
||||
systemUser.setYidaAppUserId(userId);
|
||||
userManager.registUser(systemUser);
|
||||
} else if (!systemUser.getRoleName().contains(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName())) {
|
||||
Role role = roleMapper.selectOne(Wrappers.<Role>lambdaQuery()
|
||||
.eq(Role::getRoleName, type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName()));
|
||||
userManager.addRole(systemUser.getUserId(), role.getRoleId());
|
||||
systemUser.setRoleId(systemUser.getRoleId() + "," + role.getRoleId());
|
||||
systemUser.setRoleName(systemUser.getRoleName() + "," + role.getRoleName());
|
||||
}
|
||||
// 用户未绑定appid
|
||||
if (type == 0 && teacher.getYidaAppUserId() == null) {
|
||||
remoteTeacherService.saveYidaAppUserId(teacher.getId(), userId);
|
||||
} else if (type == 1 && parent.getParentYidaAppId() == null) {
|
||||
remoteStudentService.saveYidaAppUserId(parent.getParentId(), userId);
|
||||
}
|
||||
// 登录返回token和用户信息
|
||||
Map<String, Object> res = new HashMap<>();
|
||||
res.put("token", getOauth2AccessToken(systemUser));
|
||||
systemUser.setPassword(null);
|
||||
systemUser.setIdentityId(type == 0 ? teacher.getId() : parent.getParentId());
|
||||
res.put("user", systemUser);
|
||||
res.put("identity", type == 0 ? teacher : parent);
|
||||
return res;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Map<String, Object> wxpublicLogin(String code, String appId, Integer type, Long schoolId) {
|
||||
// Dept school = null;
|
||||
// if (StringUtils.isNotBlank(appId)) {
|
||||
// school = commonService.getSchoolByAppId(appId);
|
||||
// } else if (Objects.nonNull(schoolId)) {
|
||||
// school = commonService.getDept(schoolId);
|
||||
// }
|
||||
// if (Objects.isNull(school)) {
|
||||
// throw new FebsException("学校信息错误");
|
||||
// }
|
||||
//
|
||||
// EduDeptWxPublic wxPublic = commonService.getWxPublic(school.getDeptId());
|
||||
// // 查询用户信息
|
||||
// String openId = wxPublicUtil.getOpenId(wxPublic.getAppId(), wxPublic.getSecret(), code);
|
||||
// log.info(openId);
|
||||
// // 分别为 企业用户 家长
|
||||
// ParentInfoVO parent = null;
|
||||
// EduStaff staff = null;
|
||||
// if (type == 0) {
|
||||
// staff = remoteStaffService.getStaffByWxOrMobileOrOpenId(null, null, openId, school.getDeptId()).getData();
|
||||
// } else {
|
||||
// }
|
||||
// if (staff == null && parent == null) {
|
||||
// throw new FebsException("该用户暂未注册");
|
||||
// }
|
||||
// // 教师用户查询是否绑定手机号(家长必定有手机号)
|
||||
// if (type == 0 && StrUtil.isBlank(staff.getMobile())) {
|
||||
// throw new FebsException("请绑定手机号");
|
||||
// }
|
||||
// redisService.hset(CachePrefixConstant.USER_LOGIN_DEPT, type == 0 ? staff.getMobile() :
|
||||
// parent.getMobile(), school.getDeptId());
|
||||
// // 查询系统用户
|
||||
// SystemUser systemUser = userManager.findByName(type == 0 ? staff.getMobile() : parent.getMobile());
|
||||
// // 系统用户不存在 进行注册
|
||||
// if (systemUser == null) {
|
||||
//// Role role = remoteRoleService.getRoleByNameNoPermission(type == 0 ? "教师" : "家长").getData();
|
||||
// systemUser = new SystemUser();
|
||||
// systemUser.setNickname(type == 0 ? staff.getName() : parent.getMobile());
|
||||
// systemUser.setUsername(type == 0 ? staff.getMobile() : parent.getMobile());
|
||||
// systemUser.setPassword(passwordEncoder.encode(SystemUser.DEFAULT_PASSWORD));
|
||||
// systemUser.setSex(type == 0 ? staff.getSex() : "2");
|
||||
// systemUser.setAvatar(type == 0 ? staff.getAvatar() : SystemUser.DEFAULT_AVATAR);
|
||||
// systemUser.setMobile(type == 0 ? staff.getMobile() : parent.getMobile());
|
||||
// systemUser.setUserOrigin(0);
|
||||
// systemUser.setDeptId(school.getDeptId());
|
||||
// systemUser.setRoleName(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName());
|
||||
// systemUser.setUserType(type == 0 ? 1 : 0);
|
||||
// userManager.registUser(systemUser);
|
||||
// } else if (!systemUser.getRoleName().contains(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName())) {
|
||||
// Role role = roleMapper.selectOne(Wrappers.<Role>lambdaQuery()
|
||||
// .eq(Role::getRoleName, type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName()));
|
||||
// userManager.addRole(systemUser.getUserId(), role.getRoleId());
|
||||
// systemUser.setRoleId(systemUser.getRoleId() + "," + role.getRoleId());
|
||||
// systemUser.setRoleName(systemUser.getRoleName() + "," + role.getRoleName());
|
||||
// }
|
||||
// // 登录返回token和用户信息
|
||||
// Map<String, Object> res = new HashMap<>();
|
||||
// res.put("token", getOauth2AccessToken(systemUser));
|
||||
// systemUser.setPassword(null);
|
||||
// systemUser.setIdentityId(type == 0 ? staff.getId() : parent.getParentId());
|
||||
// res.put("user", systemUser);
|
||||
// res.put("identity", type == 0 ? staff : parent);
|
||||
// return res;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Map<String, Object> wxpublicLogin(String code, String appId, Integer type, Long schoolId, String mobile) {
|
||||
Dept school = null;
|
||||
if (StringUtils.isNotBlank(appId)) {
|
||||
school = commonService.getSchoolByAppId(appId);
|
||||
} else if (Objects.nonNull(schoolId)) {
|
||||
school = commonService.getDept(schoolId);
|
||||
}
|
||||
if (Objects.isNull(school)) {
|
||||
throw new FebsException("学校信息错误");
|
||||
}
|
||||
// 查询用户信息
|
||||
String openId = wxPublicUtil.getOpenId(school.getWxPublicAppId(), school.getWxPublicSecret(), code);
|
||||
// 分别为 企业用户 家长
|
||||
ParentInfoVO parent = null;
|
||||
EduStaff teacher = null;
|
||||
// 家长和教师标识
|
||||
if (type == 0) {
|
||||
teacher = remoteStaffService.getStaffByWxOrMobileOrOpenId(null, mobile, null, school.getDeptId()).getData();
|
||||
} else {
|
||||
parent = remoteStudentService.getParentWithStudent(mobile, null, school.getDeptId()).getData();
|
||||
}
|
||||
if (teacher == null && parent == null) {
|
||||
throw new FebsException("该用户暂未注册");
|
||||
}
|
||||
redisService.hset(CachePrefixConstant.USER_LOGIN_DEPT, type == 0 ? teacher.getMobile() :
|
||||
parent.getMobile(), school.getDeptId());
|
||||
|
||||
if (type == 0) {
|
||||
teacher.setWxPublicOpenId(openId);
|
||||
remoteStaffService.saveWxPublicOpenId(teacher.getId(), openId);
|
||||
} else if (type == 1) {
|
||||
remoteStudentService.saveWxPublicOpenId(parent.getParentId(), openId);
|
||||
}
|
||||
// 查询系统用户
|
||||
SystemUser systemUser = userManager.findByName(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
// 系统用户不存在 进行注册
|
||||
if (systemUser == null) {
|
||||
systemUser = new SystemUser();
|
||||
systemUser.setNickname(type == 0 ? teacher.getName() : parent.getMobile());
|
||||
systemUser.setUsername(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
systemUser.setPassword(passwordEncoder.encode(SystemUser.DEFAULT_PASSWORD));
|
||||
systemUser.setSex(type == 0 ? teacher.getSex() : "2");
|
||||
systemUser.setAvatar(type == 0 ? teacher.getAvatar() : SystemUser.DEFAULT_AVATAR);
|
||||
systemUser.setMobile(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
systemUser.setUserOrigin(0);
|
||||
systemUser.setDeptId(school.getDeptId());
|
||||
systemUser.setRoleName(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName());
|
||||
systemUser.setUserType(type == 0 ? 1 : 0);
|
||||
userManager.registUser(systemUser);
|
||||
} else if (!systemUser.getRoleName().contains(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName())) {
|
||||
Role role = roleMapper.selectOne(Wrappers.<Role>lambdaQuery()
|
||||
.eq(Role::getRoleName, type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName()));
|
||||
userManager.addRole(systemUser.getUserId(), role.getRoleId());
|
||||
systemUser.setRoleId(systemUser.getRoleId() + "," + role.getRoleId());
|
||||
systemUser.setRoleName(systemUser.getRoleName() + "," + role.getRoleName());
|
||||
}
|
||||
// 登录返回token和用户信息
|
||||
Map<String, Object> res = new HashMap<>();
|
||||
res.put("token", getOauth2AccessToken(systemUser));
|
||||
systemUser.setPassword(null);
|
||||
systemUser.setIdentityId(type == 0 ? teacher.getId() : parent.getParentId());
|
||||
res.put("user", systemUser);
|
||||
res.put("identity", type == 0 ? teacher : parent);
|
||||
return res;
|
||||
}
|
||||
|
||||
private void createConnection(SystemUser systemUser, AuthUser authUser) {
|
||||
UserConnection userConnection = new UserConnection();
|
||||
userConnection.setUserName(systemUser.getUsername());
|
||||
userConnection.setProviderName(authUser.getSource().toString());
|
||||
userConnection.setProviderUserId(authUser.getUuid());
|
||||
userConnection.setProviderUserName(authUser.getUsername());
|
||||
userConnection.setImageUrl(authUser.getAvatar());
|
||||
userConnection.setNickName(authUser.getNickname());
|
||||
userConnection.setLocation(authUser.getLocation());
|
||||
this.userConnectionService.createUserConnection(userConnection);
|
||||
}
|
||||
|
||||
private AuthCallback resolveAuthCallback(AuthCallback callback) {
|
||||
int stateLength = 3;
|
||||
String state = callback.getState();
|
||||
String[] strings = StringUtils.splitByWholeSeparatorPreserveAllTokens(state, StringConstant.DOUBLE_COLON);
|
||||
if (strings.length == stateLength) {
|
||||
callback.setState(strings[0] + StringConstant.DOUBLE_COLON + strings[1]);
|
||||
}
|
||||
return callback;
|
||||
}
|
||||
|
||||
private AuthSource getAuthSource(String type) throws FebsException {
|
||||
if (StrUtil.isNotBlank(type)) {
|
||||
return AuthSource.valueOf(type.toUpperCase());
|
||||
} else {
|
||||
throw new FebsException(String.format("暂不支持%s第三方登录", type));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCurrentUser(String username) {
|
||||
String currentUsername = FebsUtil.getCurrentUsername();
|
||||
return StringUtils.equalsIgnoreCase(username, currentUsername);
|
||||
}
|
||||
|
||||
private OAuth2AccessToken getOauth2AccessToken(SystemUser user) throws FebsException {
|
||||
final HttpServletRequest httpServletRequest = FebsUtil.getHttpServletRequest();
|
||||
httpServletRequest.setAttribute(ParamsConstant.LOGIN_TYPE, SocialConstant.SOCIAL_LOGIN);
|
||||
String socialLoginClientId = properties.getSocialLoginClientId();
|
||||
ClientDetails clientDetails = null;
|
||||
try {
|
||||
clientDetails = redisClientDetailsService.loadClientByClientId(socialLoginClientId);
|
||||
} catch (Exception e) {
|
||||
throw new FebsException("获取第三方登录可用的Client失败");
|
||||
}
|
||||
if (clientDetails == null) {
|
||||
throw new FebsException("未找到第三方登录可用的Client");
|
||||
}
|
||||
Map<String, String> requestParameters = new HashMap<>(5);
|
||||
requestParameters.put(ParamsConstant.GRANT_TYPE, GrantTypeConstant.PASSWORD);
|
||||
requestParameters.put(USERNAME, user.getUsername());
|
||||
requestParameters.put(PASSWORD, SocialConstant.setSocialLoginPassword());
|
||||
|
||||
String grantTypes = String.join(StringConstant.COMMA, clientDetails.getAuthorizedGrantTypes());
|
||||
TokenRequest tokenRequest = new TokenRequest(requestParameters, clientDetails.getClientId(),
|
||||
clientDetails.getScope(), grantTypes);
|
||||
return granter.grant(GrantTypeConstant.PASSWORD, tokenRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> h5Login(Long schoolId, String mobile, Integer type) {
|
||||
Dept school = commonService.getDept(schoolId);
|
||||
Asserts.isNotNull(school, "该学校不存在");
|
||||
// 分别为 企业用户 家长
|
||||
ParentInfoVO parent = null;
|
||||
EduStaff teacher = null;
|
||||
// 家长和教师标识
|
||||
if (type == 0) {
|
||||
teacher = remoteStaffService.getStaffByWxOrMobileOrOpenId(null, mobile, null, school.getDeptId()).getData();
|
||||
} else {
|
||||
parent = remoteStudentService.getParentWithStudent(mobile, null, school.getDeptId()).getData();
|
||||
}
|
||||
if (teacher == null && parent == null) {
|
||||
throw new FebsException("该用户未注册");
|
||||
}
|
||||
redisService.hset(CachePrefixConstant.USER_LOGIN_DEPT, type == 0 ? teacher.getMobile() :
|
||||
parent.getMobile(), school.getDeptId());
|
||||
// 查询系统用户
|
||||
SystemUser systemUser = userManager.findByName(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
// 系统用户不存在 进行注册
|
||||
if (systemUser == null) {
|
||||
systemUser = new SystemUser();
|
||||
systemUser.setNickname(type == 0 ? teacher.getName() : parent.getMobile());
|
||||
systemUser.setUsername(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
systemUser.setPassword(passwordEncoder.encode(SystemUser.DEFAULT_PASSWORD));
|
||||
systemUser.setSex(type == 0 ? teacher.getSex() : "2");
|
||||
systemUser.setAvatar(type == 0 ? teacher.getAvatar() : SystemUser.DEFAULT_AVATAR);
|
||||
systemUser.setMobile(type == 0 ? teacher.getMobile() : parent.getMobile());
|
||||
systemUser.setUserOrigin(0);
|
||||
systemUser.setDeptId(type == 0 ? teacher.getSchoolId() : schoolId);
|
||||
systemUser.setRoleName(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName());
|
||||
systemUser.setUserType(type == 0 ? 1 : 0);
|
||||
userManager.registUser(systemUser);
|
||||
} else if (!systemUser.getRoleName().contains(type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName())) {
|
||||
Role role = roleMapper.selectOne(Wrappers.<Role>lambdaQuery()
|
||||
.eq(Role::getRoleName, type == 0 ? RoleName.STAFF.getName() : RoleName.PARENT.getName()));
|
||||
userManager.addRole(systemUser.getUserId(), role.getRoleId());
|
||||
systemUser.setRoleId(systemUser.getRoleId() + "," + role.getRoleId());
|
||||
systemUser.setRoleName(systemUser.getRoleName() + "," + role.getRoleName());
|
||||
}
|
||||
// 登录返回token和用户信息
|
||||
Map<String, Object> res = new HashMap<>();
|
||||
res.put("token", getOauth2AccessToken(systemUser));
|
||||
systemUser.setPassword(null);
|
||||
systemUser.setIdentityId(type == 0 ? teacher.getId() : parent.getParentId());
|
||||
res.put("user", systemUser);
|
||||
res.put("identity", type == 0 ? teacher : parent);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> checkOpenId(String code, Long deptId) {
|
||||
Dept school = commonService.getDept(deptId);
|
||||
if (Objects.isNull(school)) {
|
||||
throw new FebsException("学校信息错误");
|
||||
}
|
||||
// 查询用户信息
|
||||
String openId = wxPublicUtil.getOpenId(school.getWxPublicAppId(), school.getWxPublicSecret(), code);
|
||||
// 查询openId是否绑定了对应的信息
|
||||
EduSmartWelcomeGuideRosterRelation relation = remoteSmartWelcomeService.getOpenIdRelation(openId, deptId).getData();
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
// true代表已经绑定,false代表未绑定
|
||||
map.put("status", Objects.nonNull(relation));
|
||||
// 微信openId
|
||||
map.put("openId", openId);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> wxPublicLogin(String openId, Long deptId) {
|
||||
// 查询关联关系
|
||||
EduSmartWelcomeGuideRosterRelation relation = remoteSmartWelcomeService.getOpenIdRelation(openId, deptId).getData();
|
||||
if (Objects.isNull(relation) || Objects.isNull(relation.getGuideRoster())) {
|
||||
throw new FebsException("信息错误");
|
||||
}
|
||||
// 用户信息
|
||||
SystemUser systemUser = userManager.findByName(relation.getGuideRoster().getMobile());
|
||||
// 登录返回token和用户信息
|
||||
Map<String, Object> res = new HashMap<>();
|
||||
res.put("token", getOauth2AccessToken(systemUser));
|
||||
systemUser.setPassword(null);
|
||||
res.put("user", systemUser);
|
||||
// // 查询人员步骤信息
|
||||
// List<EduSmartWelcomeGuideStep> stepList = remoteSmartWelcomeService.listStepInfo(relation.getId(), relation.getGuideId()).getData();
|
||||
// relation.setStepList(stepList);
|
||||
res.put("info", relation);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.yida.data.auth.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.yida.data.auth.mapper.UserConnectionMapper;
|
||||
import com.yida.data.auth.service.UserConnectionService;
|
||||
import com.yida.data.common.core.entity.system.UserConnection;
|
||||
|
||||
/**
|
||||
* @author MrBird
|
||||
*/
|
||||
@Service
|
||||
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
|
||||
public class UserConnectionServiceImpl extends ServiceImpl<UserConnectionMapper, UserConnection> implements UserConnectionService {
|
||||
|
||||
@Override
|
||||
public UserConnection selectByCondition(String providerName, String providerUserId) {
|
||||
LambdaQueryWrapper<UserConnection> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserConnection::getProviderName, providerName)
|
||||
.eq(UserConnection::getProviderUserId, providerUserId);
|
||||
return this.baseMapper.selectOne(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserConnection> selectByCondition(String username) {
|
||||
LambdaQueryWrapper<UserConnection> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserConnection::getUserName, username);
|
||||
return this.baseMapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void createUserConnection(UserConnection userConnection) {
|
||||
this.baseMapper.insert(userConnection);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void deleteByCondition(String username, String providerName) {
|
||||
LambdaQueryWrapper<UserConnection> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(UserConnection::getUserName, username);
|
||||
queryWrapper.eq(UserConnection::getProviderName, providerName);
|
||||
this.remove(queryWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package com.yida.data.auth.service.impl;
|
||||
|
||||
import com.yida.data.auth.properties.FebsAuthProperties;
|
||||
import com.yida.data.auth.properties.FebsValidateCodeProperties;
|
||||
import com.yida.data.auth.service.ValidateCodeService;
|
||||
import com.yida.data.common.core.entity.constant.FebsConstant;
|
||||
import com.yida.data.common.core.entity.constant.ImageTypeConstant;
|
||||
import com.yida.data.common.core.entity.constant.ParamsConstant;
|
||||
import com.yida.data.common.core.exception.ValidateCodeException;
|
||||
import cc.mrbird.febs.common.redis.service.RedisService;
|
||||
import com.wf.captcha.GifCaptcha;
|
||||
import com.wf.captcha.SpecCaptcha;
|
||||
import com.wf.captcha.base.Captcha;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 验证码服务
|
||||
*
|
||||
* @author MrBird
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ValidateCodeServiceImpl implements ValidateCodeService {
|
||||
|
||||
private final RedisService redisService;
|
||||
private final FebsAuthProperties properties;
|
||||
|
||||
@Override
|
||||
public void create(HttpServletRequest request, HttpServletResponse response) throws IOException, ValidateCodeException {
|
||||
String key = request.getParameter(ParamsConstant.VALIDATE_CODE_KEY);
|
||||
if (StringUtils.isBlank(key)) {
|
||||
throw new ValidateCodeException("验证码key不能为空");
|
||||
}
|
||||
FebsValidateCodeProperties code = properties.getCode();
|
||||
setHeader(response, code.getType());
|
||||
|
||||
Captcha captcha = createCaptcha(code);
|
||||
redisService.set(FebsConstant.CODE_PREFIX + key, StringUtils.lowerCase(captcha.text()), code.getTime());
|
||||
captcha.out(response.getOutputStream());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(String key, String value) throws ValidateCodeException {
|
||||
Object codeInRedis = redisService.get(FebsConstant.CODE_PREFIX + key);
|
||||
if (StringUtils.isBlank(value)) {
|
||||
throw new ValidateCodeException("请输入验证码");
|
||||
}
|
||||
if (codeInRedis == null) {
|
||||
throw new ValidateCodeException("验证码已过期");
|
||||
}
|
||||
if (!StringUtils.equalsIgnoreCase(value, String.valueOf(codeInRedis))) {
|
||||
throw new ValidateCodeException("验证码不正确");
|
||||
}
|
||||
}
|
||||
|
||||
private Captcha createCaptcha(FebsValidateCodeProperties code) {
|
||||
Captcha captcha = null;
|
||||
if (StringUtils.equalsIgnoreCase(code.getType(), ImageTypeConstant.GIF)) {
|
||||
captcha = new GifCaptcha(code.getWidth(), code.getHeight(), code.getLength());
|
||||
} else {
|
||||
captcha = new SpecCaptcha(code.getWidth(), code.getHeight(), code.getLength());
|
||||
}
|
||||
captcha.setCharType(code.getCharType());
|
||||
return captcha;
|
||||
}
|
||||
|
||||
private void setHeader(HttpServletResponse response, String type) {
|
||||
if (StringUtils.equalsIgnoreCase(type, ImageTypeConstant.GIF)) {
|
||||
response.setContentType(MediaType.IMAGE_GIF_VALUE);
|
||||
} else {
|
||||
response.setContentType(MediaType.IMAGE_PNG_VALUE);
|
||||
}
|
||||
response.setHeader(HttpHeaders.PRAGMA, "No-cache");
|
||||
response.setHeader(HttpHeaders.CACHE_CONTROL, "No-cache");
|
||||
response.setDateHeader(HttpHeaders.EXPIRES, 0L);
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
package com.yida.data.auth.translator;
|
||||
|
||||
import com.yida.data.common.core.entity.FebsResponse;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidScopeException;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
|
||||
import org.springframework.security.oauth2.common.exceptions.RedirectMismatchException;
|
||||
import org.springframework.security.oauth2.common.exceptions.UnsupportedGrantTypeException;
|
||||
import org.springframework.security.oauth2.common.exceptions.UnsupportedResponseTypeException;
|
||||
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 异常翻译
|
||||
*
|
||||
* @author MrBird
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@SuppressWarnings("all")
|
||||
public class FebsWebResponseExceptionTranslator implements WebResponseExceptionTranslator {
|
||||
|
||||
@Override
|
||||
public ResponseEntity<?> translate(Exception e) {
|
||||
ResponseEntity.BodyBuilder status = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
ResponseEntity.BodyBuilder status1 = ResponseEntity.status(HttpStatus.PAYMENT_REQUIRED);
|
||||
FebsResponse response = new FebsResponse();
|
||||
String message = "认证失败";
|
||||
log.error(message, e);
|
||||
if (e instanceof UnsupportedGrantTypeException) {
|
||||
message = "不支持该认证类型";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
if (e instanceof InvalidTokenException
|
||||
&& StringUtils.containsIgnoreCase(e.getMessage(), "Invalid refresh token (expired)")) {
|
||||
message = "刷新令牌已过期,请重新登录";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
if (e instanceof InvalidScopeException) {
|
||||
message = "不是有效的scope值";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
if (e instanceof RedirectMismatchException) {
|
||||
message = "redirect_uri值不正确";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
if (e instanceof BadClientCredentialsException) {
|
||||
message = "client值不合法";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
if (e instanceof UnsupportedResponseTypeException) {
|
||||
String code = StringUtils.substringBetween(e.getMessage(), "[", "]");
|
||||
message = code + "不是合法的response_type值";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
if (e instanceof InvalidGrantException) {
|
||||
if (StringUtils.containsIgnoreCase(e.getMessage(), "Invalid refresh token")) {
|
||||
message = "refresh token无效";
|
||||
return status1.body(response.message(message));
|
||||
}
|
||||
if (StringUtils.containsIgnoreCase(e.getMessage(), "Invalid authorization code")) {
|
||||
String code = StringUtils.substringAfterLast(e.getMessage(), ": ");
|
||||
message = "授权码" + code + "不合法";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
if (StringUtils.containsIgnoreCase(e.getMessage(), "locked")) {
|
||||
message = "用户已被锁定,请联系管理员";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
message = "用户名或密码错误";
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
return status.body(response.message(message));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.yida.data.auth.util;
|
||||
|
||||
import com.yida.data.common.core.entity.constant.GrantTypeConstant;
|
||||
import com.yida.data.common.core.entity.constant.ParamsConstant;
|
||||
import com.yida.data.common.core.entity.constant.SocialConstant;
|
||||
import com.yida.data.common.core.entity.constant.StringConstant;
|
||||
import com.yida.data.common.core.entity.system.SystemUser;
|
||||
import com.yida.data.common.core.exception.FebsException;
|
||||
import com.yida.data.common.core.utils.FebsUtil;
|
||||
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.provider.ClientDetails;
|
||||
import org.springframework.security.oauth2.provider.TokenRequest;
|
||||
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.yida.data.auth.properties.FebsAuthProperties;
|
||||
import com.yida.data.auth.service.impl.RedisClientDetailsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class SecurityUtil {
|
||||
|
||||
private final FebsAuthProperties properties;
|
||||
private final RedisClientDetailsService redisClientDetailsService;
|
||||
private final ResourceOwnerPasswordTokenGranter granter;
|
||||
|
||||
private static final String USERNAME = "username";
|
||||
private static final String PASSWORD = "password";
|
||||
|
||||
public OAuth2AccessToken getOauth2AccessToken(SystemUser user) throws FebsException {
|
||||
final HttpServletRequest httpServletRequest = FebsUtil.getHttpServletRequest();
|
||||
httpServletRequest.setAttribute(ParamsConstant.LOGIN_TYPE, SocialConstant.SOCIAL_LOGIN);
|
||||
String socialLoginClientId = properties.getSocialLoginClientId();
|
||||
ClientDetails clientDetails = null;
|
||||
try {
|
||||
clientDetails = redisClientDetailsService.loadClientByClientId(socialLoginClientId);
|
||||
} catch (Exception e) {
|
||||
throw new FebsException("获取第三方登录可用的Client失败");
|
||||
}
|
||||
if (clientDetails == null) {
|
||||
throw new FebsException("未找到第三方登录可用的Client");
|
||||
}
|
||||
Map<String, String> requestParameters = new HashMap<>(5);
|
||||
requestParameters.put(ParamsConstant.GRANT_TYPE, GrantTypeConstant.PASSWORD);
|
||||
requestParameters.put(USERNAME, user.getUsername());
|
||||
requestParameters.put(PASSWORD, SocialConstant.setSocialLoginPassword());
|
||||
|
||||
String grantTypes = String.join(StringConstant.COMMA, clientDetails.getAuthorizedGrantTypes());
|
||||
TokenRequest tokenRequest = new TokenRequest(requestParameters, clientDetails.getClientId(), clientDetails.getScope(), grantTypes);
|
||||
return granter.grant(GrantTypeConstant.PASSWORD, tokenRequest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
required=\u4E0D\u80FD\u4E3A\u7A7A
|
||||
noMoreThan=\u957f\u5ea6\u4e0d\u80fd\u8d85\u8fc7{max}\u4e2a\u5b57\u7b26
|
||||
invalidNumber=\u4e0d\u662f\u6709\u6548\u7684\u6570\u503c
|
||||
@@ -0,0 +1,8 @@
|
||||
|------------------------------|
|
||||
| ____ ____ ___ __ |
|
||||
| | |_ | |_ | |_) ( (` |
|
||||
| |_| |_|__ |_|_) _)_) |
|
||||
| |
|
||||
| ${spring.application.name} |
|
||||
| Spring-Boot: ${spring-boot.version} |
|
||||
|------------------------------|
|
||||
@@ -0,0 +1,34 @@
|
||||
spring:
|
||||
profiles:
|
||||
active: "@env-name@"
|
||||
application:
|
||||
name: Edu-Auth
|
||||
cloud:
|
||||
nacos:
|
||||
config:
|
||||
server-addr: ${nacos.url}
|
||||
group: DEFAULT_GROUP
|
||||
prefix: edu-auth
|
||||
file-extension: yaml
|
||||
discovery:
|
||||
server-addr: ${nacos.url}
|
||||
thymeleaf:
|
||||
cache: false
|
||||
|
||||
logging:
|
||||
level:
|
||||
org:
|
||||
springframework:
|
||||
boot:
|
||||
actuate:
|
||||
endpoint:
|
||||
EndpointId: error
|
||||
com:
|
||||
alibaba:
|
||||
cloud:
|
||||
nacos:
|
||||
client:
|
||||
NacosPropertySourceBuilder: error
|
||||
nacos:
|
||||
client:
|
||||
naming: warn
|
||||
@@ -0,0 +1,9 @@
|
||||
febs.auth.enableJwt=false
|
||||
febs.auth.jwtAccessKey=febs
|
||||
febs.auth.socialLoginClientId=app
|
||||
febs.auth.code.time=120
|
||||
febs.auth.code.type=png
|
||||
febs.auth.code.width=115
|
||||
febs.auth.code.height=42
|
||||
febs.auth.code.length=4
|
||||
febs.auth.code.charType=2
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.yida.data.auth.mapper.MenuMapper">
|
||||
|
||||
<select id="findUserPermissions" resultType="java.lang.String">
|
||||
select distinct m.perms
|
||||
from t_role r
|
||||
left join t_user_role ur on (r.role_id = ur.role_id)
|
||||
left join t_user u on (u.user_id = ur.user_id)
|
||||
left join t_role_menu rm on (rm.role_id = r.role_id)
|
||||
left join t_menu m on (m.menu_id = rm.menu_id)
|
||||
where u.username = #{userName}
|
||||
and m.perms is not null
|
||||
and m.perms <> ''
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.yida.data.auth.mapper.UserMapper">
|
||||
<select id="findByName" parameterType="string"
|
||||
resultType="com.yida.data.common.core.entity.system.SystemUser">
|
||||
SELECT u.user_id userId,
|
||||
u.username,
|
||||
u.nickname,
|
||||
u.email,
|
||||
u.mobile,
|
||||
u.password,
|
||||
u.status,
|
||||
u.create_time createTime,
|
||||
u.ssex sex,
|
||||
u.dept_id deptId,
|
||||
u.last_login_time lastLoginTime,
|
||||
u.modify_time modifyTime,
|
||||
u.description,
|
||||
u.avatar,
|
||||
d.dept_type deptType,
|
||||
d.school_nature schoolNature,
|
||||
d.dept_name deptName,
|
||||
u.agent_id agentId,
|
||||
GROUP_CONCAT(r.role_id) roleId,
|
||||
GROUP_CONCAT(r.ROLE_NAME) roleName,
|
||||
GROUP_CONCAT( r.ROLE_PERMS ) rolePerms,
|
||||
u.create_id,
|
||||
u.create_dept_id,
|
||||
u.main_dept_id,
|
||||
u.open_id
|
||||
FROM t_user u
|
||||
LEFT JOIN t_dept d ON (u.dept_id = d.dept_id)
|
||||
LEFT JOIN t_user_role ur ON (u.user_id = ur.user_id)
|
||||
LEFT JOIN t_role r ON r.role_id = ur.role_id
|
||||
WHERE u.username = #{username}
|
||||
group by u.username, u.user_id, u.email, u.mobile, u.password, u.status, u.create_time, u.ssex,
|
||||
u.dept_id
|
||||
, u.last_login_time, u.modify_time, u.description, u.avatar
|
||||
</select>
|
||||
|
||||
<select id="findUserDataPermissions" parameterType="long"
|
||||
resultType="com.yida.data.common.core.entity.system.UserDataPermission">
|
||||
select user_id userId, dept_id deptId
|
||||
from t_user_data_permission
|
||||
where user_id = #{userId}
|
||||
</select>
|
||||
|
||||
<select id="listUserByPerms" resultType="com.yida.data.common.core.entity.system.SystemUser">
|
||||
select a.*
|
||||
from t_user a left join t_user_role b on a.USER_ID=b.USER_ID
|
||||
left join t_role c on b.ROLE_ID=c.ROLE_ID
|
||||
where c.ROLE_PERMS=#{perms}
|
||||
<if test="deptId != null">
|
||||
and a.DEPT_ID=#{deptId}
|
||||
</if>
|
||||
order by a.USER_ID
|
||||
</select>
|
||||
|
||||
<!-- 查询主角色code字符串 -->
|
||||
<select id="findMainRole"
|
||||
resultType="java.lang.String">
|
||||
SELECT
|
||||
distinct
|
||||
r.ROLE_PERMS
|
||||
FROM
|
||||
t_user u
|
||||
INNER JOIN t_user_role ur ON u.USER_ID = ur.USER_ID
|
||||
INNER JOIN t_role r ON ur.ROLE_ID = r.ROLE_ID
|
||||
WHERE
|
||||
u.DEPT_ID = #{mainDeptId}
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.yida.data.auth.mapper.UserMenuMapper">
|
||||
|
||||
<select id="findUserPermissions" resultType="com.yida.data.common.core.entity.system.SystemUserMenu">
|
||||
select um.*, m.perms
|
||||
from t_user_menu um
|
||||
left join t_user u on (u.user_id = um.user_id)
|
||||
left join t_menu m on (m.menu_id = um.menu_id)
|
||||
where u.username = #{userName}
|
||||
and m.perms is not null
|
||||
and m.perms <![CDATA[!=]]> ''
|
||||
</select>
|
||||
</mapper>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
*{box-sizing:border-box;margin:0;padding:0;font-weight:600;}body{font-family:"Helvetica Neue",Helvetica,Tahoma,Arial,'PingFang SC','Source Han Sans CN','Source Han Sans','Hiragino Sans GB','WenQuanYi Micro Hei',sans-serif;color:white;font-weight:600;}body::-webkit-input-placeholder{font-family:"Helvetica Neue",Helvetica,Tahoma,Arial,'PingFang SC','Source Han Sans CN','Source Han Sans','Hiragino Sans GB','WenQuanYi Micro Hei',sans-serif;color:white;font-weight:600;}body:-moz-placeholder{font-family:"Helvetica Neue",Helvetica,Tahoma,Arial,'PingFang SC','Source Han Sans CN','Source Han Sans','Hiragino Sans GB','WenQuanYi Micro Hei',sans-serif;color:white;opacity:1;font-weight:600;}body::-moz-placeholder{font-family:"Helvetica Neue",Helvetica,Tahoma,Arial,'PingFang SC','Source Han Sans CN','Source Han Sans','Hiragino Sans GB','WenQuanYi Micro Hei',sans-serif;color:white;opacity:1;font-weight:600;}body:-ms-input-placeholder{font-family:"Helvetica Neue",Helvetica,Tahoma,Arial,'PingFang SC','Source Han Sans CN','Source Han Sans','Hiragino Sans GB','WenQuanYi Micro Hei',sans-serif;color:white;font-weight:600;}.wrapper{background-image:linear-gradient(120deg,#e0c3fc 0%,#8ec5fc 100%);position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;}.wrapper.form-success .container h1{-webkit-transform:translateY(85px);transform:translateY(85px);}.container{max-width:600px;margin:0 auto;padding:200px 0;height:400px;text-align:center;}.container h1{font-size:30px;-webkit-transition-duration:1s;transition-duration:1s;-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;font-weight:500;}form{padding:20px 0;position:relative;z-index:2;}form input{-webkit-appearance:none;-moz-appearance:none;appearance:none;outline:0;border:1px solid rgba(255,255,255,0.4);background-color:rgba(255,255,255,0.2);width:300px;border-radius:3px;padding:10px 15px;margin:0 auto 15px auto;display:block;text-align:center;font-size:18px;color:white;-webkit-transition-duration:0.25s;transition-duration:0.25s;font-weight:600;}form input:hover{background-color:rgba(255,255,255,0.4);}form input:focus{background-color:white;width:350px;color:#a6b1e1;}form button{-webkit-appearance:none;-moz-appearance:none;appearance:none;outline:0;background-color:white;border:0;padding:10px 15px;color:#a6b1e1;border-radius:3px;width:300px;cursor:pointer;font-size:18px;-webkit-transition-duration:0.25s;transition-duration:0.25s;}form button:hover{background-color:#f5f7f9;}.bg-bubbles{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;}.bg-bubbles li{position:absolute;list-style:none;display:block;width:40px;height:40px;background-color:rgba(255,255,255,0.15);bottom:-160px;-webkit-animation:square 25s infinite;animation:square 25s infinite;-webkit-transition-timing-function:linear;transition-timing-function:linear;}.bg-bubbles li:nth-child(1){left:10%;}.bg-bubbles li:nth-child(2){left:20%;width:80px;height:80px;-webkit-animation-delay:2s;animation-delay:2s;-webkit-animation-duration:17s;animation-duration:17s;}.bg-bubbles li:nth-child(3){left:25%;-webkit-animation-delay:4s;animation-delay:4s;}.bg-bubbles li:nth-child(4){left:40%;width:60px;height:60px;-webkit-animation-duration:22s;animation-duration:22s;background-color:rgba(255,255,255,0.25);}.bg-bubbles li:nth-child(5){left:70%;}.bg-bubbles li:nth-child(6){left:80%;width:120px;height:120px;-webkit-animation-delay:3s;animation-delay:3s;background-color:rgba(255,255,255,0.2);}.bg-bubbles li:nth-child(7){left:32%;width:160px;height:160px;-webkit-animation-delay:7s;animation-delay:7s;}.bg-bubbles li:nth-child(8){left:55%;width:20px;height:20px;-webkit-animation-delay:15s;animation-delay:15s;-webkit-animation-duration:40s;animation-duration:40s;}.bg-bubbles li:nth-child(9){left:25%;width:10px;height:10px;-webkit-animation-delay:2s;animation-delay:2s;-webkit-animation-duration:40s;animation-duration:40s;background-color:rgba(255,255,255,0.3);}.bg-bubbles li:nth-child(10){left:90%;width:160px;height:160px;-webkit-animation-delay:11s;animation-delay:11s;}@-webkit-keyframes square{0%{-webkit-transform:translateY(0);transform:translateY(0);}100%{-webkit-transform:translateY(-700px) rotate(600deg);transform:translateY(-700px) rotate(600deg);}}@keyframes square{0%{-webkit-transform:translateY(0);transform:translateY(0);}100%{-webkit-transform:translateY(-700px) rotate(600deg);transform:translateY(-700px) rotate(600deg);}}
|
||||
@@ -0,0 +1 @@
|
||||
$(function(){var a=$("#username"),b=$("#password");$("#login").on("click",function(c){var d,e;return c.preventDefault(),d=a.val().trim(),e=b.val().trim(),""===d?(alert("用户名不能为空"),void 0):""===e?(alert("密码不能为空"),void 0):($.post(ctx+"login",{username:d,password:e},function(a){window.location.href=a.data}).error(function(a){console.error(a),alert(a.responseJSON.message)}),void 0)})});
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ch" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
|
||||
name="viewport">
|
||||
<meta content="ie=edge" http-equiv="X-UA-Compatible">
|
||||
<link rel="icon" th:href="@{resource/favicon.ico}" type="image/x-icon"/>
|
||||
<title>第三方登录失败</title>
|
||||
</head>
|
||||
<style>
|
||||
span{font-size:.9rem;font-weight:bold;color:#42b983}
|
||||
</style>
|
||||
<body>
|
||||
<span>[[${error}]]</span>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ch" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
|
||||
name="viewport">
|
||||
<meta name="description" content="FEBS Cloud授权码模式登录页面">
|
||||
<meta name="author" content="MrBird">
|
||||
<link rel="stylesheet" th:href="@{resource/login.min.css}" media="all">
|
||||
<script th:src="@{resource/jQuery-2.1.4.min.js}"></script>
|
||||
<link rel="icon" th:href="@{resource/favicon.ico}" type="image/x-icon"/>
|
||||
<title>FEBS系统登录</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="container"><h1>FEBS 系统登录</h1>
|
||||
<form class="form"><input type="text" placeholder="用户名" id="username"><input type="password" placeholder="密码"
|
||||
id="password">
|
||||
<button type="submit" id="login">登录</button>
|
||||
</form>
|
||||
</div>
|
||||
<ul class="bg-bubbles">
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
<li></li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
<script th:inline="javascript">
|
||||
var ctx = [[@{/}]];
|
||||
</script>
|
||||
<script th:src="@{resource/login.min.js}"></script>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ch" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"
|
||||
name="viewport">
|
||||
<meta content="ie=edge" http-equiv="X-UA-Compatible">
|
||||
<link rel="icon" th:href="@{resource/favicon.ico}" type="image/x-icon"/>
|
||||
<title>登录跳转中</title>
|
||||
</head>
|
||||
<body>
|
||||
登录中..
|
||||
<script th:inline="javascript">
|
||||
var response = [[${response}]];
|
||||
var frontUrl = [[${frontUrl}]];
|
||||
window.onload = function () {
|
||||
window.opener.postMessage(response, frontUrl);
|
||||
window.close();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>test</title>
|
||||
</head>
|
||||
<body>
|
||||
<a
|
||||
href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=wwbbc43a5b210ddb23&redirect_uri=http%3A%2F%2Fzbz.yd-data.com%3A8301%2Fauth%2Ftest&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect">test</a>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user