parent
b8d0d44e92
commit
41ef7f4b6c
21 changed files with 532 additions and 4 deletions
@ -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(); |
||||
} |
||||
} |
@ -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"); // 登录成功跳转路径
|
||||
} |
||||
} |
||||
|
@ -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(); |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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> { |
||||
|
||||
UserEntity getUser(String code); |
||||
int selectCount(String phoneAccount); |
||||
int updatePasswordByPhoneAccount(@Param("phoneAccount") String phoneAccount, @Param("password") String password); |
||||
} |
@ -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<UserEntity> { |
||||
Boolean getBackPwd(UserLoginRequest user); |
||||
} |
@ -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<UserLoginDao, UserEntity> implements UserLoginService, UserDetailsService { |
||||
|
||||
@Resource |
||||
private UserLoginDao userLoginDao; |
||||
|
||||
@Override |
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { |
||||
UserEntity user = userLoginDao.getUser(username); |
||||
List<SimpleGrantedAuthority> 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<UserEntity>() |
||||
.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; |
||||
} |
||||
} |
@ -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.daqing.financial.hrauth.dao.UserLoginDao"> |
||||
<update id="updatePasswordByPhoneAccount"> |
||||
update hrms_user set password = #{password} where phone_account = #{phoneAccount} |
||||
</update> |
||||
|
||||
<select id="getUser" parameterType="string" resultType="com.daqing.framework.domain.hrms.UserEntity"> |
||||
SELECT account,password FROM hrms_user WHERE account = #{account} |
||||
</select> |
||||
<select id="selectCount" resultType="java.lang.Integer"> |
||||
select count(1) from hrms_user where phone_account = #{phoneAccount} |
||||
</select> |
||||
|
||||
</mapper> |
@ -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()); |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,34 @@ |
||||
package com.daqing.framework.domain.hrms.request; |
||||
|
||||
import lombok.Data; |
||||
|
||||
import java.io.Serializable; |
||||
|
||||
/** |
||||
* 登录找回密码请求体对象 |
||||
* |
||||
* @author gongsj |
||||
* @email gongsj@gmail.com |
||||
* @date 2020-09-07 17:12:14 |
||||
*/ |
||||
@Data |
||||
public class UserLoginRequest implements Serializable { |
||||
|
||||
/** |
||||
* 手机账号 |
||||
*/ |
||||
private String phoneAccount; |
||||
/**A |
||||
* 密码 |
||||
*/ |
||||
private String password; |
||||
|
||||
/** |
||||
* 验证码 |
||||
*/ |
||||
private String verifyCode; |
||||
/** |
||||
* 新密码 |
||||
*/ |
||||
private String newPwd; |
||||
} |
Binary file not shown.
Loading…
Reference in new issue