diff --git a/dq-financial-hrms-auth/pom.xml b/dq-financial-hrms-auth/pom.xml index eafd1d2a..baabf2e7 100644 --- a/dq-financial-hrms-auth/pom.xml +++ b/dq-financial-hrms-auth/pom.xml @@ -50,6 +50,34 @@ + + + + org.springframework.cloud + spring-cloud-starter-security + + + org.springframework.security + spring-security-jwt + 1.1.1.RELEASE + + + io.jsonwebtoken + jjwt + 0.9.0 + + + org.springframework.security.oauth + spring-security-oauth2 + + 2.3.3.RELEASE + + + + com.baomidou + mybatis-plus-boot-starter + 3.0.5 + diff --git a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/DqFinancialHrmsAuthApplication.java b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/DqFinancialHrmsAuthApplication.java index 3a5828a1..f03a6e6c 100644 --- a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/DqFinancialHrmsAuthApplication.java +++ b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/DqFinancialHrmsAuthApplication.java @@ -2,8 +2,14 @@ package com.daqing.financial.hrauth; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.ComponentScan; +@EnableFeignClients(basePackages = "com.daqing.financial.hrauth.feign") +@EnableDiscoveryClient @SpringBootApplication +@ComponentScan(basePackages = "com.daqing") public class DqFinancialHrmsAuthApplication { public static void main(String[] args) { diff --git a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/AuthorizationServer.java b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/AuthorizationServer.java new file mode 100644 index 00000000..0afbaf5a --- /dev/null +++ b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/AuthorizationServer.java @@ -0,0 +1,109 @@ +package com.daqing.financial.hrauth.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.authentication.AuthenticationManager; +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.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.ClientDetailsService; +import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices; +import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices; +import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; +import org.springframework.security.oauth2.provider.token.DefaultTokenServices; +import org.springframework.security.oauth2.provider.token.TokenStore; + +/** + * 配置OAuth2.0授权服务器 + * + * @auther River + * @date 2020/9/21 17:49 + */ +@Configuration +@EnableAuthorizationServer +public class AuthorizationServer extends AuthorizationServerConfigurerAdapter { + + @Autowired + private TokenStore tokenStore; + + @Autowired + private ClientDetailsService clientDetailsService; + + @Autowired + private AuthenticationManager authenticationManager; + + @Autowired + private AuthorizationCodeServices authorizationCodeServices; + @Autowired + public PasswordEncoder passwordEncoder; + + /** + * 配置令牌的安全约束(允许哪些请求访问) + */ + @Override + public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { + security + .tokenKeyAccess("permitAll()") // 公开提供公钥加密的端点(就是使用jwt令牌的时候需要的) + .checkTokenAccess("permitAll()") // 校验令牌 + .allowFormAuthenticationForClients(); //允许表单提交,允许客户端访问 OAuth2 授权接口,否则请求 token 会返回 401。 + } + + /** + * 配置支持哪些客户端访问 + */ + @Override + public void configure(ClientDetailsServiceConfigurer clients) throws Exception { + clients.inMemory() + .withClient("order-client") + .secret(passwordEncoder.encode("order-secret-8888")) + .authorizedGrantTypes("refresh_token", "authorization_code", "password") + .accessTokenValiditySeconds(3600) + .scopes("all") + .and() + .withClient("user-client") + .secret(passwordEncoder.encode("user-secret-8888")) + .authorizedGrantTypes("refresh_token", "authorization_code", "password") + .accessTokenValiditySeconds(3600) + .scopes("all"); + } + + /** + * 配置令牌(token)的访问端点 + */ + @Override + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { + endpoints + .authenticationManager(authenticationManager) // 密码模式需要 + .authorizationCodeServices(authorizationCodeServices) // 授权码模式需要 + .tokenServices(tokenServices()) // 令牌的管理方式 + .allowedTokenEndpointRequestMethods(HttpMethod.POST); // 允许的请求方式 + } + + /** + * 令牌服务 + */ + @Bean + public AuthorizationServerTokenServices tokenServices(){ + DefaultTokenServices service = new DefaultTokenServices(); + service.setClientDetailsService(clientDetailsService); // 客户端信息的服务 + service.setSupportRefreshToken(true); // 是否产生刷新令牌 + service.setTokenStore(tokenStore); // 令牌的存储策略 + service.setAccessTokenValiditySeconds(7200); // 令牌有效期 + service.setRefreshTokenValiditySeconds(259200); // 刷新令牌有效期 + return service; + } + + /** + * 授权码服务(设置授权码模式的授权码如何存取,暂时在内存,后期在数据库) + */ + @Bean + public AuthorizationCodeServices authorizationCodeServices(){ + + return new InMemoryAuthorizationCodeServices(); + } +} diff --git a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/SecurityConfig.java b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/SecurityConfig.java new file mode 100644 index 00000000..a558a568 --- /dev/null +++ b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/SecurityConfig.java @@ -0,0 +1,67 @@ +package com.daqing.financial.hrauth.config; + +import com.daqing.financial.hrauth.service.impl.UserLoginServiceImpl; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +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.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * @auther River + * @date 2020/9/22 10:26 + */ +@Configuration +@EnableWebSecurity // 开启security +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + /** + * 不能直接new对象,否则会在注入之前被拦截器拦截 + */ + @Bean + public UserLoginServiceImpl customerLoginService(){ + + return new UserLoginServiceImpl(); + } + + // 定义用户信息(查询用户信息),security帮助我们查询,但是需要告诉他如何去查询 + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + + auth.userDetailsService(customerLoginService()); + } + + + // 密码编码器,比对密码的方式 + @Bean + public PasswordEncoder passwordEncoder(){ + + return new BCryptPasswordEncoder(); + } + + /** + * 认证管理器 + */ + @Override + @Bean + public AuthenticationManager authenticationManagerBean() throws Exception { + + return super.authenticationManagerBean(); + } + + // 安全拦截机制 + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers("/*").authenticated() // 该路径下所有请求都会被拦截 + .anyRequest().permitAll() // 其余的请求可以通过 + .and() + .formLogin() // 允许表单认证 + .successForwardUrl("/customerLogin/loginSuccess"); // 登录成功跳转路径 + } +} + diff --git a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/TokenConfig.java b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/TokenConfig.java new file mode 100644 index 00000000..10df81ec --- /dev/null +++ b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/config/TokenConfig.java @@ -0,0 +1,22 @@ +package com.daqing.financial.hrauth.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.provider.token.TokenStore; +import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; + +/** + * 令牌配置类 + * + * @auther River + * @date 2020/9/22 9:54 + */ +@Configuration +public class TokenConfig { + + @Bean + public TokenStore tokenStore(){ + // 内存生成,普通令牌 + return new InMemoryTokenStore(); + } +} diff --git a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/controller/UserLoginController.java b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/controller/UserLoginController.java new file mode 100644 index 00000000..365b35f8 --- /dev/null +++ b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/controller/UserLoginController.java @@ -0,0 +1,37 @@ +package com.daqing.financial.hrauth.controller; + +import com.daqing.financial.hrauth.service.UserLoginService; +import com.daqing.framework.domain.hrms.request.UserLoginRequest; +import com.daqing.framework.model.response.ResponseResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * @auther River + * @date 2020/9/22 15:27 + */ +@RestController +@RequestMapping("/hrms/auth/userlogin") +public class UserLoginController { + + @Autowired + private UserLoginService userLoginService; + + @PostMapping("/loginSuccess") + public String loginSuccess(){ + + return "success"; + } + + @GetMapping("/test") + public String test(){ + + return "Hello"; + } + + @PostMapping("/getBackPwd") + public ResponseResult getBackPwd(@RequestBody UserLoginRequest user){ + boolean result = userLoginService.getBackPwd(user); + return result ? ResponseResult.SUCCESS() : ResponseResult.FAIL(); + } +} diff --git a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/dao/UserLoginDao.java b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/dao/UserLoginDao.java new file mode 100644 index 00000000..9f7e0c18 --- /dev/null +++ b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/dao/UserLoginDao.java @@ -0,0 +1,18 @@ +package com.daqing.financial.hrauth.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.daqing.framework.domain.hrms.UserEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * @auther River + * @date 2020/9/22 14:55 + */ +@Mapper +public interface UserLoginDao extends BaseMapper { + + UserEntity getUser(String code); + int selectCount(String phoneAccount); + int updatePasswordByPhoneAccount(@Param("phoneAccount") String phoneAccount, @Param("password") String password); +} diff --git a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/service/UserLoginService.java b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/service/UserLoginService.java new file mode 100644 index 00000000..5e884bfd --- /dev/null +++ b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/service/UserLoginService.java @@ -0,0 +1,13 @@ +package com.daqing.financial.hrauth.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.daqing.framework.domain.hrms.UserEntity; +import com.daqing.framework.domain.hrms.request.UserLoginRequest; + +/** + * @auther River + * @date 2020/9/22 15:00 + */ +public interface UserLoginService extends IService { + Boolean getBackPwd(UserLoginRequest user); +} diff --git a/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/service/impl/UserLoginServiceImpl.java b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/service/impl/UserLoginServiceImpl.java new file mode 100644 index 00000000..b2e27c6b --- /dev/null +++ b/dq-financial-hrms-auth/src/main/java/com/daqing/financial/hrauth/service/impl/UserLoginServiceImpl.java @@ -0,0 +1,81 @@ +package com.daqing.financial.hrauth.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.daqing.financial.hrauth.dao.UserLoginDao; +import com.daqing.financial.hrauth.service.UserLoginService; +import com.daqing.framework.domain.hrms.UserEntity; +import com.daqing.framework.domain.hrms.request.UserLoginRequest; +import com.daqing.framework.domain.hrms.response.HrmsCode; +import com.daqing.framework.exception.ExceptionCast; +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.User; +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.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @auther River + * @date 2020/9/22 15:01 + */ +@Service("userLoginService") +public class UserLoginServiceImpl extends ServiceImpl implements UserLoginService, UserDetailsService { + + @Resource + private UserLoginDao userLoginDao; + + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + UserEntity user = userLoginDao.getUser(username); + List authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN")); + System.out.println(user); + UserDetails userDetails = new User(user.getAccount(),new BCryptPasswordEncoder().encode(user.getPassword()),authorities); + + return userDetails; + } + + /** + * 忘记密码 + */ + @Override + public Boolean getBackPwd(UserLoginRequest user){ + //判断重置密码参数是否为空 + if(StringUtils.isEmpty(user.getPhoneAccount())){ + ExceptionCast.cast(HrmsCode.PHNOE_ACCOUNT_ILLEGAL); + } + if(StringUtils.isEmpty(user.getVerifyCode())){ + ExceptionCast.cast(HrmsCode.VERIFY_CODE_ILLEGAL); + } + if(StringUtils.isEmpty(user.getNewPwd())){ + ExceptionCast.cast(HrmsCode.NEW_PASSWORD_NOT_EMPTY); + } + //校验手机账号是否存在 + int count = this.count(new QueryWrapper() + .eq("phone_account", user.getPhoneAccount())); + if (count == 0) { + ExceptionCast.cast(HrmsCode.PHNOE_ACCOUNT_ILLEGAL); + } + //判断验证码是否匹配 + + //密码格式校验 + Pattern pattern = Pattern.compile("^[a-zA-Z0-9]{8,20}$"); + Matcher match = pattern.matcher(user.getNewPwd()); + if(!match.matches()){ + ExceptionCast.cast(HrmsCode.NEW_PASSWORD_ILLEGAL); + } + String newMD5 = new BCryptPasswordEncoder().encode(user.getNewPwd()); + //根据手机号码修改密码 + int i = userLoginDao.updatePasswordByPhoneAccount(user.getPhoneAccount(),newMD5); + return i > 0; + } +} diff --git a/dq-financial-hrms-auth/src/main/resources/application.properties b/dq-financial-hrms-auth/src/main/resources/application.properties deleted file mode 100644 index 8b137891..00000000 --- a/dq-financial-hrms-auth/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ - diff --git a/dq-financial-hrms-auth/src/main/resources/bootstrap.properties b/dq-financial-hrms-auth/src/main/resources/bootstrap.properties new file mode 100644 index 00000000..40330e13 --- /dev/null +++ b/dq-financial-hrms-auth/src/main/resources/bootstrap.properties @@ -0,0 +1,19 @@ + +#�������� +spring.application.name=dq-financial-hrms +#�������ĵ�ַ +spring.cloud.nacos.config.server-addr=192.168.31.142:8848 +spring.cloud.nacos.config.namespace=7632bdaa-3381-4669-b3f9-2fc73be451e8 +#spring.cloud.nacos.config.group=prod + +spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml +spring.cloud.nacos.config.ext-config[0].group=dev +spring.cloud.nacos.config.ext-config[0].refresh=true + +spring.cloud.nacos.config.ext-config[1].data-id=mybatis.yml +spring.cloud.nacos.config.ext-config[1].group=dev +spring.cloud.nacos.config.ext-config[1].refresh=true + +spring.cloud.nacos.config.ext-config[2].data-id=other.yml +spring.cloud.nacos.config.ext-config[2].group=dev +spring.cloud.nacos.config.ext-config[2].refresh=true diff --git a/dq-financial-hrms-auth/src/main/resources/mapper/hrmsauth/UserLoginMapper.xml b/dq-financial-hrms-auth/src/main/resources/mapper/hrmsauth/UserLoginMapper.xml new file mode 100644 index 00000000..00a7fad6 --- /dev/null +++ b/dq-financial-hrms-auth/src/main/resources/mapper/hrmsauth/UserLoginMapper.xml @@ -0,0 +1,16 @@ + + + + + + update hrms_user set password = #{password} where phone_account = #{phoneAccount} + + + + + + \ No newline at end of file diff --git a/dq-financial-hrms/pom.xml b/dq-financial-hrms/pom.xml index 13f8b1c2..1f131e57 100644 --- a/dq-financial-hrms/pom.xml +++ b/dq-financial-hrms/pom.xml @@ -61,6 +61,13 @@ + + + org.springframework.security.oauth + spring-security-oauth2 + 2.3.5.RELEASE + compile + diff --git a/dq-financial-hrms/src/main/java/com/daqing/financial/hrms/config/ResourceServerConfig.java b/dq-financial-hrms/src/main/java/com/daqing/financial/hrms/config/ResourceServerConfig.java new file mode 100644 index 00000000..e04fd7d8 --- /dev/null +++ b/dq-financial-hrms/src/main/java/com/daqing/financial/hrms/config/ResourceServerConfig.java @@ -0,0 +1,47 @@ +package com.daqing.financial.hrms.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; +import org.springframework.security.oauth2.provider.token.RemoteTokenServices; + +@Configuration +@EnableResourceServer +@EnableGlobalMethodSecurity(prePostEnabled = true) +public class ResourceServerConfig extends ResourceServerConfigurerAdapter { + + @Value("${security.oauth2.client.client-id}") + private String clientId; + + @Value("${security.oauth2.client.client-secret}") + private String secret; + + @Value("${security.oauth2.authorization.check-token-access}") + private String checkTokenEndpointUrl; + + /* @Autowired + private RedisConnectionFactory redisConnectionFactory;*/ + +/* @Bean + public TokenStore redisTokenStore (){ + return new RedisTokenStore(redisConnectionFactory); + }*/ + + @Bean + public RemoteTokenServices tokenService() { + RemoteTokenServices tokenService = new RemoteTokenServices(); + tokenService.setClientId(clientId); + tokenService.setClientSecret(secret); + tokenService.setCheckTokenEndpointUrl(checkTokenEndpointUrl); + return tokenService; + } + + @Override + public void configure(ResourceServerSecurityConfigurer resources) throws Exception { + resources.tokenServices(tokenService()); + } +} \ No newline at end of file diff --git a/dq-financial-hrms/src/main/java/com/daqing/financial/hrms/controller/UserController.java b/dq-financial-hrms/src/main/java/com/daqing/financial/hrms/controller/UserController.java index e76563a5..a2545da2 100644 --- a/dq-financial-hrms/src/main/java/com/daqing/financial/hrms/controller/UserController.java +++ b/dq-financial-hrms/src/main/java/com/daqing/financial/hrms/controller/UserController.java @@ -5,6 +5,9 @@ import com.daqing.framework.domain.hrms.UserEntity; import com.daqing.framework.model.response.ResponseResult; import com.daqing.framework.utils.PageUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails; import org.springframework.web.bind.annotation.*; import java.util.Arrays; @@ -79,4 +82,19 @@ public class UserController { return ResponseResult.SUCCESS(); } + /** + * 只有当访问用户具有 ROLE_ADMIN 权限时才能访问,否则返回 401 未授权。 + * 通过 Authentication 参数或者 SecurityContextHolder.getContext().getAuthentication() 可以拿到授权信息进行查看。 + * @param authentication + * @return + */ + @GetMapping(value = "get") + @PreAuthorize("hasAnyRole('ROLE_ADMIN')") + public Object get(Authentication authentication){ + //Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + authentication.getCredentials(); + OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)authentication.getDetails(); + String token = details.getTokenValue(); + return token; + } } diff --git a/dq-financial-hrms/target/classes/com/daqing/financial/hrms/controller/UserController.class b/dq-financial-hrms/target/classes/com/daqing/financial/hrms/controller/UserController.class index 949f0700..83fb4a9d 100644 Binary files a/dq-financial-hrms/target/classes/com/daqing/financial/hrms/controller/UserController.class and b/dq-financial-hrms/target/classes/com/daqing/financial/hrms/controller/UserController.class differ diff --git a/dq-financial-hrms/target/classes/mapper/hrms/EmployeeDao.xml b/dq-financial-hrms/target/classes/mapper/hrms/EmployeeDao.xml index 12205e22..2a7a70fe 100644 --- a/dq-financial-hrms/target/classes/mapper/hrms/EmployeeDao.xml +++ b/dq-financial-hrms/target/classes/mapper/hrms/EmployeeDao.xml @@ -65,7 +65,8 @@