diff --git a/pom.xml b/pom.xml index 5885e3a..3490cc0 100644 --- a/pom.xml +++ b/pom.xml @@ -195,6 +195,21 @@ simplecaptcha 1.2.2 + + + org.springframework.boot + spring-boot-starter-data-redis + + + com.qms.utils + QmsUtils + 1.1.6.RELEASE + + + org.projectlombok + lombok + 1.16.14 + diff --git a/src/main/java/com/blueskykong/auth/AuthApplication.java b/src/main/java/com/blueskykong/auth/AuthApplication.java index f518d61..6c04b5f 100644 --- a/src/main/java/com/blueskykong/auth/AuthApplication.java +++ b/src/main/java/com/blueskykong/auth/AuthApplication.java @@ -1,11 +1,12 @@ package com.blueskykong.auth; - import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; /** * @@ -14,9 +15,10 @@ */ @SpringBootApplication -//@EnableFeignClients +@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) +@EnableFeignClients //@EnableDiscoveryClient -public class AuthApplication { +public class AuthApplication extends WebSecurityConfigurerAdapter { public static void main(String[] args) { SpringApplication.run(AuthApplication.class, args); diff --git a/src/main/java/com/blueskykong/auth/client/fallback/UserFallbackClient.java b/src/main/java/com/blueskykong/auth/client/fallback/UserFallbackClient.java deleted file mode 100644 index 81fabe9..0000000 --- a/src/main/java/com/blueskykong/auth/client/fallback/UserFallbackClient.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.blueskykong.auth.client.fallback; - -import com.blueskykong.auth.client.feign.UserClient; -import com.blueskykong.auth.exception.ErrorCodes; -import com.blueskykong.auth.exception.RemoteException; -import org.springframework.stereotype.Component; - -import java.util.Map; - -/** - * @author keets - * @date 2017/9/25 - */ -@Component -public class UserFallbackClient implements UserClient { - - @Override - public Map checkUsernameAndPassword(Map userMap) { - throw new RemoteException(ErrorCodes.USER_SERVICE_CALL_FAILURE); - } - - @Override - public Map getUserInformation(Map userCheck) { - throw new RemoteException(ErrorCodes.USER_SERVICE_CALL_FAILURE); - } - -} diff --git a/src/main/java/com/blueskykong/auth/client/feign/UserClient.java b/src/main/java/com/blueskykong/auth/client/feign/UserClient.java index da5dbe9..ff50707 100644 --- a/src/main/java/com/blueskykong/auth/client/feign/UserClient.java +++ b/src/main/java/com/blueskykong/auth/client/feign/UserClient.java @@ -1,24 +1,27 @@ package com.blueskykong.auth.client.feign; -import com.blueskykong.auth.client.fallback.UserFallbackClient; +import com.blueskykong.auth.dto.UserInfoDTO; +import com.qms.utils.entity.GeneralVO; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; - -import java.util.Map; +import org.springframework.web.bind.annotation.RequestParam; /** * @author keets * @date 2017/9/25 */ -@FeignClient(name = "user", fallback = UserFallbackClient.class) -public interface UserClient { - @RequestMapping(method = RequestMethod.POST, value = "/api/users/exists", consumes = {"application/json"}, produces = {"application/json"}) - Map checkUsernameAndPassword(Map userMap); - - @RequestMapping(method = RequestMethod.POST, value = "/api/users/phoneExists", consumes = {"application/json"}, produces = {"application/json"}) - Map getUserInformation(Map userCheck); +//@FeignClient(value = "user", url="https://test.meia8.com/qmsuser/user") +@FeignClient(value = "user", url="http://localhost:8080/qmsuser/user") +public interface UserClient { + /** + * 根据c端用户名查询用户详情 + * @param userName + * @return + */ + @RequestMapping(value="/queryInfoByName", method = { RequestMethod.POST}) + GeneralVO queryUseInfoByUserName(@RequestParam("userName") String userName); } diff --git a/src/main/java/com/blueskykong/auth/config/oauth/OAuth2Config.java b/src/main/java/com/blueskykong/auth/config/oauth/Oauth2Config.java similarity index 52% rename from src/main/java/com/blueskykong/auth/config/oauth/OAuth2Config.java rename to src/main/java/com/blueskykong/auth/config/oauth/Oauth2Config.java index 96b0698..c2ddc48 100644 --- a/src/main/java/com/blueskykong/auth/config/oauth/OAuth2Config.java +++ b/src/main/java/com/blueskykong/auth/config/oauth/Oauth2Config.java @@ -1,49 +1,46 @@ package com.blueskykong.auth.config.oauth; import com.blueskykong.auth.security.CustomAuthorizationTokenServices; -import com.blueskykong.auth.security.CustomTokenEnhancer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.security.authentication.AuthenticationManager; 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.client.JdbcClientDetailsService; import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; -import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; -import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; - -import javax.sql.DataSource; +import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; /** - * Created by keets on 2017/9/25. + * 配置Oauth2.0 + * 1. 配置token存储为redis + * 2. 配置用户username,password的数据库验证数据源 + * 3. 配置内存clientId,secret用于验证请求的client是否合法 + * @author figo */ - @Configuration @EnableAuthorizationServer -public class OAuth2Config extends AuthorizationServerConfigurerAdapter { +public class Oauth2Config extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Autowired - private DataSource dataSource; + private WebResponseExceptionTranslator webResponseExceptionTranslator; @Autowired - private WebResponseExceptionTranslator webResponseExceptionTranslator; + private RedisConnectionFactory redisConnectionFactory; - @Bean - public JdbcClientDetailsService clientDetailsService(DataSource dataSource) { - return new JdbcClientDetailsService(dataSource); - } + @Autowired + private RedisTokenStore redisTokenStore; @Bean - public JdbcTokenStore tokenStore(DataSource dataSource) { - return new JdbcTokenStore(dataSource); + public RedisTokenStore tokenStore(RedisConnectionFactory redisConnectionFactory) { + return new RedisTokenStore(redisConnectionFactory); } @Override @@ -53,33 +50,53 @@ public void configure(AuthorizationServerSecurityConfigurer security) throws Exc @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { - clients.withClientDetails(clientDetailsService(dataSource)); + //配置客户端,用于password认证 + clients.inMemory() + .withClient("frontend") + .authorizedGrantTypes("password", "refresh_token") + .scopes("select") + .authorities("client") + .secret("frontend") + .and() + .withClient("waiter") + .authorizedGrantTypes("password", "refresh_token") + .scopes("select") + .authorities("client") + .secret("waiter") + .and() + .withClient("shop") + .authorizedGrantTypes("password", "refresh_token") + .scopes("select") + .authorities("client") + .secret("shop") + .and() + .withClient("customer") + .authorizedGrantTypes("password", "refresh_token") + .scopes("select") + .authorities("client") + .secret("customer") + .and() + .withClient("platform") + .authorizedGrantTypes("password", "refresh_token") + .scopes("select") + .authorities("client") + .secret("platform"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager) - .tokenStore(tokenStore(dataSource)) + .tokenStore(redisTokenStore) .tokenServices(authorizationServerTokenServices()) - .accessTokenConverter(accessTokenConverter()) .exceptionTranslator(webResponseExceptionTranslator); } - @Bean - public JwtAccessTokenConverter accessTokenConverter() { - JwtAccessTokenConverter converter = new CustomTokenEnhancer(); - converter.setSigningKey("secret"); - return converter; - } - @Bean public AuthorizationServerTokenServices authorizationServerTokenServices() { CustomAuthorizationTokenServices customTokenServices = new CustomAuthorizationTokenServices(); - customTokenServices.setTokenStore(tokenStore(dataSource)); + customTokenServices.setTokenStore(redisTokenStore); + customTokenServices.setAccessTokenValiditySeconds(-1); customTokenServices.setSupportRefreshToken(true); - customTokenServices.setReuseRefreshToken(true); - customTokenServices.setClientDetailsService(clientDetailsService(dataSource)); - customTokenServices.setTokenEnhancer(accessTokenConverter()); return customTokenServices; } } diff --git a/src/main/java/com/blueskykong/auth/config/oauth/ResourceServerConfig.java b/src/main/java/com/blueskykong/auth/config/oauth/ResourceServerConfig.java index a8142f1..1af9514 100644 --- a/src/main/java/com/blueskykong/auth/config/oauth/ResourceServerConfig.java +++ b/src/main/java/com/blueskykong/auth/config/oauth/ResourceServerConfig.java @@ -1,7 +1,6 @@ package com.blueskykong.auth.config.oauth; import com.blueskykong.auth.security.filter.CustomLogoutHandler; -import com.blueskykong.auth.security.filter.CustomSecurityFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -9,7 +8,6 @@ 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.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; /** * @author keets @@ -24,15 +22,13 @@ public void configure(HttpSecurity http) throws Exception { http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() - .requestMatchers().antMatchers("/**") - .and().authorizeRequests() - .antMatchers("/**").permitAll() - .anyRequest().authenticated() - .and().logout() + .antMatcher("/me") + .authorizeRequests().anyRequest().authenticated(); + /*.and().logout() .logoutUrl("/logout") .clearAuthentication(true) .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()) - .addLogoutHandler(customLogoutHandler()); + .addLogoutHandler(customLogoutHandler());*/ //http.antMatcher("/api/**").addFilterAt(customSecurityFilter(), FilterSecurityInterceptor.class); diff --git a/src/main/java/com/blueskykong/auth/dao/UserDao.java b/src/main/java/com/blueskykong/auth/dao/UserDao.java new file mode 100644 index 0000000..4efa563 --- /dev/null +++ b/src/main/java/com/blueskykong/auth/dao/UserDao.java @@ -0,0 +1,35 @@ +package com.blueskykong.auth.dao; + +import org.apache.ibatis.annotations.Mapper; + +import java.util.Map; + +/** + * @author figo + */ +@Mapper +public interface UserDao { + + /** + * 获取店铺账户信息 + * @param map + * @return + */ + Map getShopAccount(Map map); + + + /** + * 获取服务员信息 + * @param map + * @return + */ + Map getWaiter(Map map); + + /** + * 获取平台用户 + * @param map + * @return + */ + Map getPlatformUser(Map map); + +} diff --git a/src/main/java/com/blueskykong/auth/dao/impl/MybatisClientSecretDAO.java b/src/main/java/com/blueskykong/auth/dao/impl/MybatisClientSecretDAOImpl.java similarity index 97% rename from src/main/java/com/blueskykong/auth/dao/impl/MybatisClientSecretDAO.java rename to src/main/java/com/blueskykong/auth/dao/impl/MybatisClientSecretDAOImpl.java index 432f64f..e030057 100644 --- a/src/main/java/com/blueskykong/auth/dao/impl/MybatisClientSecretDAO.java +++ b/src/main/java/com/blueskykong/auth/dao/impl/MybatisClientSecretDAOImpl.java @@ -13,7 +13,7 @@ import java.util.UUID; @Repository -public class MybatisClientSecretDAO implements ClientSecretDAO { +public class MybatisClientSecretDAOImpl implements ClientSecretDAO { @Autowired private ClientSecretMapper mapper; diff --git a/src/main/java/com/blueskykong/auth/dao/impl/UserDaoImpl.java b/src/main/java/com/blueskykong/auth/dao/impl/UserDaoImpl.java new file mode 100644 index 0000000..7472d86 --- /dev/null +++ b/src/main/java/com/blueskykong/auth/dao/impl/UserDaoImpl.java @@ -0,0 +1,49 @@ +package com.blueskykong.auth.dao.impl; + +import com.blueskykong.auth.dao.UserDao; +import com.blueskykong.auth.dao.mapper.UserMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import java.util.Map; + +/** + * @author figo + */ +@Repository +public class UserDaoImpl implements UserDao { + + @Autowired + private UserMapper mapper; + + /** + * 获取店铺账户信息 + * @param map + * @return + */ + @Override + public Map getShopAccount(Map map){ + return mapper.getShopAccount(map); + } + + + /** + * 获取服务员信息 + * @param map + * @return + */ + @Override + public Map getWaiter(Map map){ + return mapper.getWaiter(map); + } + + /** + * 获取平台用户 + * @param map + * @return + */ + @Override + public Map getPlatformUser(Map map){ + return mapper.getPlatformUser(map); + } +} diff --git a/src/main/java/com/blueskykong/auth/dao/mapper/UserMapper.java b/src/main/java/com/blueskykong/auth/dao/mapper/UserMapper.java new file mode 100644 index 0000000..4cc5bdd --- /dev/null +++ b/src/main/java/com/blueskykong/auth/dao/mapper/UserMapper.java @@ -0,0 +1,33 @@ +package com.blueskykong.auth.dao.mapper; + +import java.util.Map; + +/** + * 对用户信息的操作 + * @author figo + */ +public interface UserMapper { + + /** + * 获取店铺账户信息 + * @param map + * @return + */ + Map getShopAccount(Map map); + + + /** + * 获取服务员信息 + * @param map + * @return + */ + Map getWaiter(Map map); + + /** + * 获取平台用户 + * @param map + * @return + */ + Map getPlatformUser(Map map); + +} diff --git a/src/main/java/com/blueskykong/auth/dto/UserInfoDTO.java b/src/main/java/com/blueskykong/auth/dto/UserInfoDTO.java new file mode 100644 index 0000000..43059ad --- /dev/null +++ b/src/main/java/com/blueskykong/auth/dto/UserInfoDTO.java @@ -0,0 +1,68 @@ +package com.blueskykong.auth.dto; + +import com.qms.utils.entity.BaseEntity; +import lombok.Data; + +/** + * @title: UserInfoVo + * @package: com.qms.user.entity.vo + * @description: + * @anther: dongzhanbiao + * @date: 2017-09-27 上午11:03 + * @author figo + */ +@Data +public class UserInfoDTO extends BaseEntity { + + /** + * 用户标识ID + */ + private String userId; + /** + * 用户名 + */ + private String userName; + + /** + * 密码 + */ + private String passWord; + + /** + * 真是姓名 + */ + private String realName; + /** + * 用户昵称 + */ + private String userNick; + /** + * 用户性别 + */ + private Integer userSex; + /** + * 用户生日 + */ + private String userBirthday; + /** + * 省 + */ + private String province; + /** + * 市 + */ + private String city; + /** + * 区 + */ + private String district; + /** + * 地址 + */ + private String address; + /** + * 用户头像地址 + */ + private String userHeadpic; + +} \ No newline at end of file diff --git a/src/main/java/com/blueskykong/auth/entity/ClientSecretStatus.java b/src/main/java/com/blueskykong/auth/entity/ClientSecretStatus.java index 9d4d930..33d6c72 100644 --- a/src/main/java/com/blueskykong/auth/entity/ClientSecretStatus.java +++ b/src/main/java/com/blueskykong/auth/entity/ClientSecretStatus.java @@ -4,5 +4,9 @@ * Created by keets on 2016/12/5. */ public enum ClientSecretStatus { - ACTIVE, INACTIVE + //活跃 + ACTIVE, + + //非活跃 + INACTIVE } diff --git a/src/main/java/com/blueskykong/auth/rest/ClientSecretResource.java b/src/main/java/com/blueskykong/auth/rest/ClientSecretResource.java index 730ceba..32fc262 100644 --- a/src/main/java/com/blueskykong/auth/rest/ClientSecretResource.java +++ b/src/main/java/com/blueskykong/auth/rest/ClientSecretResource.java @@ -1,24 +1,21 @@ package com.blueskykong.auth.rest; -import com.blueskykong.auth.dto.ApiClientDTO; -import com.blueskykong.auth.entity.ClientSecretStatus; -import com.blueskykong.auth.service.ClientSecretService; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; -import javax.ws.rs.*; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.util.List; -import java.util.UUID; +import java.security.Principal; +import java.util.LinkedHashMap; +import java.util.Map; /** * @author keets * @date 2017/9/18 */ -@Path("/") +@RestController +@RequestMapping("/") public class ClientSecretResource { - @Autowired + /*@Autowired private ClientSecretService clientSecretService; @POST @@ -47,5 +44,12 @@ public Response getClient(@PathParam("clientId") String clientId) { public Response updateClient(@PathParam("clientId") String clientId, ApiClientDTO apiClientDTO) { clientSecretService.updateClientSecret(apiClientDTO); return Response.ok().build(); + }*/ + + @RequestMapping({ "/user", "/me" }) + public Map user(Principal principal) { + Map map = new LinkedHashMap<>(); + map.put("username", principal.getName()); + return map; } } diff --git a/src/main/java/com/blueskykong/auth/rest/SecurityResource.java b/src/main/java/com/blueskykong/auth/rest/SecurityResource.java index c5c4c26..e272536 100644 --- a/src/main/java/com/blueskykong/auth/rest/SecurityResource.java +++ b/src/main/java/com/blueskykong/auth/rest/SecurityResource.java @@ -32,7 +32,7 @@ public Response logout(@QueryParam("token") String token) { OAuth2AccessToken existingAccessToken = tokenStore.readAccessToken(token); OAuth2RefreshToken refreshToken; - if (existingAccessToken != null) { + /*if (existingAccessToken != null) { if (existingAccessToken.getRefreshToken() != null) { LOGGER.info("remove refreshToken!"); refreshToken = existingAccessToken.getRefreshToken(); @@ -40,7 +40,7 @@ public Response logout(@QueryParam("token") String token) { } LOGGER.info("remove existingAccessToken!"); tokenStore.removeAccessToken(existingAccessToken); - } + }*/ return Response.ok().build(); } diff --git a/src/main/java/com/blueskykong/auth/security/CustomAuthenticationProvider.java b/src/main/java/com/blueskykong/auth/security/CustomAuthenticationProvider.java index 1d9cecd..b28aeda 100644 --- a/src/main/java/com/blueskykong/auth/security/CustomAuthenticationProvider.java +++ b/src/main/java/com/blueskykong/auth/security/CustomAuthenticationProvider.java @@ -1,18 +1,20 @@ package com.blueskykong.auth.security; -import com.blueskykong.auth.client.feign.UserClient; import com.auth0.jwt.internal.org.apache.commons.lang3.StringUtils; +import com.blueskykong.auth.service.UserService; +import com.qms.utils.security.CustomAuthenticationToken; +import com.qms.utils.security.CustomUserDetails; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Component; import org.springframework.util.Assert; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; /** * @author keets @@ -22,46 +24,56 @@ public class CustomAuthenticationProvider implements AuthenticationProvider { @Autowired - private UserClient userClient; + private UserService userService; + /** + * 根据用户名、密码进行身份认证 + * @param authentication + * @return + * @throws AuthenticationException + */ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password; Map data = (Map) authentication.getDetails(); - String clientId = (String) data.get("client"); + String clientId = (String) data.get("clientId"); Assert.hasText(clientId, "clientId must have value"); String type = (String) data.get("type"); Map map; password = (String) authentication.getCredentials(); - //如果你是调用user服务,这边不用注掉 - //map = userClient.checkUsernameAndPassword(getUserServicePostObject(username, password, type)); - map = checkUsernameAndPassword(getUserServicePostObject(username, password, type)); + //根据用户类型,验证用户的用户名密码,并返回用户对象信息。 + map = userService.getUser(getUserServicePostObject(username, password, type)); - - String userId = (String) map.get("userId"); + //userId做非null及非空字符串判断,另外不同的用户类型,id可能为string/int/long等类型 + String userId = ""; + Object userIdObj = map.get("userId"); + if (userIdObj != null) { + userId = userIdObj.toString(); + } if (StringUtils.isBlank(userId)) { String errorCode = (String) map.get("code"); throw new BadCredentialsException(errorCode); } - CustomUserDetails customUserDetails = buildCustomUserDetails(username, password, userId, clientId); + + CustomUserDetails customUserDetails = buildCustomUserDetails(username, password, userId, clientId, type); return new CustomAuthenticationToken(customUserDetails); } - private CustomUserDetails buildCustomUserDetails(String username, String password, String userId, String clientId) { - CustomUserDetails customUserDetails = new CustomUserDetails.CustomUserDetailsBuilder() + private CustomUserDetails buildCustomUserDetails(String username, String password, String userId, String clientId, String type) { + return new CustomUserDetails.CustomUserDetailsBuilder() .withUserId(userId) .withPassword(password) .withUsername(username) .withClientId(clientId) + .withAuthorities(getAuthorities(type)) .build(); - return customUserDetails; } private Map getUserServicePostObject(String username, String password, String type) { Map requestParam = new HashMap(); - requestParam.put("userName", username); + requestParam.put("username", username); requestParam.put("password", password); if (type != null && StringUtils.isNotBlank(type)) { requestParam.put("type", type); @@ -69,19 +81,24 @@ private Map getUserServicePostObject(String username, String pas return requestParam; } - //模拟调用user服务的方法 - private Map checkUsernameAndPassword(Map map) { - - //checkUsernameAndPassword - Map ret = new HashMap(); - ret.put("userId", UUID.randomUUID().toString()); - - return ret; - } - @Override public boolean supports(Class aClass) { return true; } + /** + * 设置用户角色权限 + * @param type + * @return + * + * // TODO: 06/12/2017 通过用户类型,简单设置用户的权限角色,后期需要在网关上扩展。 + */ + private Collection getAuthorities(String type){ + String authority = org.apache.commons.lang3.StringUtils.upperCase(type); + Set authSet = new HashSet<>(); + authSet.add(new SimpleGrantedAuthority("ROLE_" + authority)); + + return authSet; + } + } \ No newline at end of file diff --git a/src/main/java/com/blueskykong/auth/security/CustomAuthenticationToken.java b/src/main/java/com/blueskykong/auth/security/CustomAuthenticationToken.java deleted file mode 100644 index 961fd0c..0000000 --- a/src/main/java/com/blueskykong/auth/security/CustomAuthenticationToken.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.blueskykong.auth.security; - -import org.springframework.security.authentication.AbstractAuthenticationToken; - -/** - * Created by keets on 2017/8/5. - */ -public class CustomAuthenticationToken extends AbstractAuthenticationToken { - - private CustomUserDetails userDetails; - - public CustomAuthenticationToken(CustomUserDetails userDetails) { - super(null); - this.userDetails = userDetails; - super.setAuthenticated(true); - } - - public Object getPrincipal() { - return this.userDetails; - } - - public Object getCredentials() { - return this.userDetails.getPassword(); - } - -} \ No newline at end of file diff --git a/src/main/java/com/blueskykong/auth/security/CustomAuthorizationTokenServices.java b/src/main/java/com/blueskykong/auth/security/CustomAuthorizationTokenServices.java index 4ddeb2a..6e66885 100644 --- a/src/main/java/com/blueskykong/auth/security/CustomAuthorizationTokenServices.java +++ b/src/main/java/com/blueskykong/auth/security/CustomAuthorizationTokenServices.java @@ -22,12 +22,16 @@ /** * Created by keets on 2017/8/5. + * + * @author figo */ public class CustomAuthorizationTokenServices implements AuthorizationServerTokenServices, ConsumerTokenServices { - private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 days. + // default 30 days. + private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; - private int accessTokenValiditySeconds = 60 * 60 * 12; // default 12 hours. + // default 12 hours. + private int accessTokenValiditySeconds = 60 * 60 * 12; private boolean supportRefreshToken = false; @@ -49,7 +53,7 @@ public void afterPropertiesSet() throws Exception { } @Override - @Transactional + @Transactional(rollbackFor = Exception.class) public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication); diff --git a/src/main/java/com/blueskykong/auth/security/CustomTokenEnhancer.java b/src/main/java/com/blueskykong/auth/security/CustomTokenEnhancer.java index bb7cdc8..512e77c 100644 --- a/src/main/java/com/blueskykong/auth/security/CustomTokenEnhancer.java +++ b/src/main/java/com/blueskykong/auth/security/CustomTokenEnhancer.java @@ -1,5 +1,6 @@ package com.blueskykong.auth.security; +import com.qms.utils.security.CustomUserDetails; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; diff --git a/src/main/java/com/blueskykong/auth/security/CustomUserDetails.java b/src/main/java/com/blueskykong/auth/security/CustomUserDetails.java deleted file mode 100644 index a7e6312..0000000 --- a/src/main/java/com/blueskykong/auth/security/CustomUserDetails.java +++ /dev/null @@ -1,124 +0,0 @@ -package com.blueskykong.auth.security; - -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -import java.util.Collection; - -/** - * @author keets - * @date 2017/8/5 - */ -public class CustomUserDetails implements UserDetails { - static final long serialVersionUID = -7588980448693010399L; - private String username; - - private String password; - - private boolean enabled = true; - - private String userId; - - private String clientId; - - private Collection authorities; - - public String getClientId() { - return clientId; - } - - public void setClientId(String clientId) { - this.clientId = clientId; - } - - public String getUserId() { - return userId; - } - - public void setUsername(String username) { - this.username = username; - } - - public void setPassword(String password) { - this.password = password; - } - - - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - - public void setAuthorities(Collection authorities) { - this.authorities = authorities; - } - - @Override - public Collection getAuthorities() { - return authorities; - } - - @Override - public String getPassword() { - return this.password; - } - - @Override - public String getUsername() { - return this.username; - } - - @Override - public boolean isAccountNonExpired() { - return true; - } - - @Override - public boolean isAccountNonLocked() { - return true; - } - - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - @Override - public boolean isEnabled() { - return enabled; - } - - public static class CustomUserDetailsBuilder { - private CustomUserDetails userDetails = new CustomUserDetails(); - - public CustomUserDetailsBuilder withUsername(String username) { - userDetails.setUsername(username); - userDetails.setAuthorities(null); - return this; - } - - public CustomUserDetailsBuilder withPassword(String password) { - userDetails.setPassword(password); - return this; - } - - public CustomUserDetailsBuilder withClientId(String clientId) { - userDetails.setClientId(clientId); - return this; - } - - public CustomUserDetailsBuilder withUserId(String userId) { - userDetails.setUserId(userId); - return this; - } - - public CustomUserDetails build() { - return userDetails; - } - } - -} diff --git a/src/main/java/com/blueskykong/auth/service/UserService.java b/src/main/java/com/blueskykong/auth/service/UserService.java new file mode 100644 index 0000000..eb7c9d1 --- /dev/null +++ b/src/main/java/com/blueskykong/auth/service/UserService.java @@ -0,0 +1,86 @@ +package com.blueskykong.auth.service; + +import com.blueskykong.auth.client.feign.UserClient; +import com.blueskykong.auth.dao.UserDao; +import com.blueskykong.auth.dto.UserInfoDTO; +import com.qms.utils.ErrorListEnum; +import com.qms.utils.entity.GeneralVO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * 用户业务服务 + * @author figo + * Created by figo on 01/12/2017. + */ + +@Service +public class UserService { + + @Autowired + private UserDao userDao; + + @Autowired + private UserClient userClient; + + /** + * 根据客户端用户类型如C端用户/B端商户/W端服务员/P端管理员等, + * 分别到对应的数据表中进行用户名和密码的验证。 + * @param map + * @return + */ + public Map getUser(Map map){ + + String type = map.get("type"); + switch (type){ + case "customer": + map = getCustomer(map); + break; + case "shop": + map = userDao.getShopAccount(map); + break; + case "waiter": + map = userDao.getWaiter(map); + break; + case "platform": + map = userDao.getPlatformUser(map); + break; + default:{} + } + + return map!=null ? map : new HashMap(0); + } + + /** + * 获取C端用户信息 + * @param map + * @return + */ + private Map getCustomer(Map map){ + String username = map.get("username"); + String password = map.get("password"); + + GeneralVO result = userClient.queryUseInfoByUserName(username); + if (result == null) { + return new HashMap(0); + } + if (!Objects.equals(result.getCode(), ErrorListEnum.E200.getKey())){ + return new HashMap(0); + } + if(result.getBody() == null){ + return new HashMap(0); + } + + UserInfoDTO userInfo = (UserInfoDTO) result.getBody(); + if (Objects.equals(password, userInfo.getPassWord())){ + map.put("userId", userInfo.getUserId()); + return map; + } + + return new HashMap(0); + } +} diff --git a/src/main/java/com/blueskykong/auth/utils/TimestampAdapter.java b/src/main/java/com/blueskykong/auth/utils/TimestampAdapter.java index cb2a655..4b0de42 100644 --- a/src/main/java/com/blueskykong/auth/utils/TimestampAdapter.java +++ b/src/main/java/com/blueskykong/auth/utils/TimestampAdapter.java @@ -11,8 +11,8 @@ import java.text.SimpleDateFormat; public class TimestampAdapter extends XmlAdapter { - private static final DatatypeFactory df; - private static final ThreadLocal simpleDateFormat = new ThreadLocal(){ + private static final DatatypeFactory DF; + private static final ThreadLocal SIMPLE_DATE_FORMAT = new ThreadLocal(){ @Override protected DateFormat initialValue() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -21,7 +21,7 @@ protected DateFormat initialValue() { static { try { - df = DatatypeFactory.newInstance(); + DF = DatatypeFactory.newInstance(); } catch (DatatypeConfigurationException e) { throw Throwables.propagate(e); } @@ -30,14 +30,14 @@ protected DateFormat initialValue() { @Override public String marshal(Timestamp v) throws Exception { if (v != null) { - return simpleDateFormat.get().format(v); + return SIMPLE_DATE_FORMAT.get().format(v); } return null; } @Override public Timestamp unmarshal(String v) throws Exception { - XMLGregorianCalendar cal = df.newXMLGregorianCalendar(v); + XMLGregorianCalendar cal = DF.newXMLGregorianCalendar(v); try { return new Timestamp(cal.toGregorianCalendar().getTimeInMillis()); } catch (Exception e) { diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 9ce03a7..162e3e2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,36 +6,14 @@ spring: maximum-pool-size: 5 pool-name: dbcp1 driver-class-name: com.mysql.jdbc.Driver - url: jdbc:mysql://116.62.146.35:3307/auth?autoReconnect=true&useSSL=false - username: ${AUTH_DB_PWD:root} - password: ${AUTH_DB_USER:root123} + url: jdbc:mysql://rm-2ze2g7ns6cx4y9346o.mysql.rds.aliyuncs.com:3306/qmsdb + username: ${AUTH_DB_PWD:qmsdb} + password: ${AUTH_DB_USER:jk23RuF!@9isaHf23} type: com.zaxxer.hikari.HikariDataSource - -############################# Redis config ############################# -cache: - # pool config - pool: - maxIdle: 15 - maxTotal: 30 - maxWaitMillis: 6000 - minIdle: 1 - numTestsPerEvictionRun: 10 - testOnBorrow: true - testOnReturn: true - testWhileIdle: true - timeBetweenEvictionRunsMillis: 6000 - # enable redis redis: - enabled: true -# if flush all the cache when start up -redis: - database: 0 - host: - address: ${REDIS_ADDRESS:116.62.146.35} - password: ${REDIS_PWD:} - port: ${REDIS_PORT:7000} - setup: - flushdb: true + port: ${REDIS_PORT:16339} + host: ${REDIS_ADDRESS:101.201.177.32} + password: ${REDIS_PWD:02681330-d47f-4e34-a0fc-4a2f8931c523} ribbon: ReadTimeout: 10000 @@ -48,4 +26,3 @@ hystrix: strategy: THREAD thread: timeoutInMilliseconds: 10000 - diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml index b77c380..9539368 100644 --- a/src/main/resources/bootstrap.yml +++ b/src/main/resources/bootstrap.yml @@ -1,5 +1,6 @@ server: port: 9000 + context-path: /auth --- spring: diff --git a/src/main/resources/mybatis/mapper/UserMapper.xml b/src/main/resources/mybatis/mapper/UserMapper.xml new file mode 100644 index 0000000..814e9da --- /dev/null +++ b/src/main/resources/mybatis/mapper/UserMapper.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + diff --git a/src/test/com.blueskykong.auth.controller/TokenEndpointTest.java b/src/test/com.blueskykong.auth.controller/TokenEndpointTest.java new file mode 100644 index 0000000..24eb907 --- /dev/null +++ b/src/test/com.blueskykong.auth.controller/TokenEndpointTest.java @@ -0,0 +1,138 @@ +package com.blueskykong.auth.controller; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.netflix.feign.FeignAutoConfiguration; +import org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration; +import org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +/** + * Created by figo on 24/11/2017. + * + * @author figo + */ + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +@ImportAutoConfiguration({RibbonAutoConfiguration.class, FeignRibbonClientAutoConfiguration.class, FeignAutoConfiguration.class}) +public class TokenEndpointTest { + + @Autowired + private MockMvc mvc; + + /** + * 测试获取C端用户账户token + * @throws Exception + */ + @Test + public void getCustomerOauthToken() throws Exception { + + MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/oauth/token") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .header("authorization", "Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,") + .param("grant_type", "password") + .param("username", "18966922934") + .param("password", "E0369B31012DC0BCD11221B7D49C16AF") + .param("clientId", "frontend") + .param("type", "customer") + ) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + + int statusCode = result.getResponse().getStatus(); + Assert.assertEquals(statusCode, 200); + String body = result.getResponse().getContentAsString(); + System.out.println("body:" + body); + + } + + /** + * 测试获取店铺账户token + * @throws Exception + */ + @Test + public void getShopOauthToken() throws Exception { + + MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/oauth/token") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .header("authorization", "Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,") + .param("grant_type", "password") + .param("username", "13689248182") + .param("password", "E0369B31012DC0BCD11221B7D49C16AF") + .param("clientId", "frontend") + .param("type", "shop") + ) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + + int statusCode = result.getResponse().getStatus(); + Assert.assertEquals(statusCode, 200); + String body = result.getResponse().getContentAsString(); + System.out.println("body:" + body); + + } + + /** + * 测试获取服务员token + * @throws Exception + */ + @Test + public void getWaiterOauthToken() throws Exception { + + MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/oauth/token") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .header("authorization", "Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,") + .param("grant_type", "password") + .param("username", "15839396565") + .param("password", "123456") + .param("clientId", "frontend") + .param("type", "waiter") + ) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + + int statusCode = result.getResponse().getStatus(); + Assert.assertEquals(statusCode, 200); + String body = result.getResponse().getContentAsString(); + System.out.println("body:" + body); + + } + + /** + * 测试获取平台用户token + * @throws Exception + */ + @Test + public void getPlatformUserOauthToken() throws Exception { + + MvcResult result = mvc.perform(MockMvcRequestBuilders.post("/oauth/token") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .header("authorization", "Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,") + .param("grant_type", "password") + .param("username", "admin") + .param("password", "123123") + .param("clientId", "frontend") + .param("type", "platform") + ) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn(); + + int statusCode = result.getResponse().getStatus(); + Assert.assertEquals(statusCode, 200); + String body = result.getResponse().getContentAsString(); + System.out.println("body:" + body); + + } +}