上一篇文章《实战Spring Cloud Oauth2系列(二)实战编写一个oauth认证服务器》我们编写了一个oauth2的服务端,同时可以跑起来了,大家可以测试下,这篇文章我们介绍下自定义查询用户的数据结构。
在使用spring security编写oauth2的时候,我们可以看到没有编写任何一个接口,此时在这里查询user表的数据的时候,就完全是oauth这套框架来完成的。但是在实际的场景里面,我们会涉及到一些实际定义的用户数据结构,那么此时我们怎么来操作呢?
其实在上一篇文章的时候,我们介绍了,在oauthconfig的这个类里面有一个方法:
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.userDetailsService(userService) .authenticationManager(authenticationManager) .tokenStore(this.getJdbcTokenStore()); }
在这里我们就可以自定义个这个查询的类,然后我们使用endpoints.userDetailsService这个方法来配置我们自己的user查询类。在前面的源码里面已经呈现了,这里我们来看看这个类的具体实现:
package org.shop.oauth.server.service; import org.springframework.security.core.userdetails.UserDetailsService; public interface UserService extends UserDetailsService{ }
首先如果我们需要自定义一个user查询方法的话,那么我们需要创建一个类,这个类必须要继承自UserDetailsService这个类。当集成这个类之后,这里就只有一个方法:
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{}
我们实现这个方法的逻辑就是根据用户名来查询对应的用户,具体的实现如下:
package org.shop.oauth.server.service.impl; import org.shop.common.http.exception.ShopException; import org.shop.common.model.http.ResultCode; import org.shop.common.mysql.auth.mapper.UserEntityDao; import org.shop.common.mysql.auth.model.UserEntity; import org.shop.common.mysql.auth.model.UserPrincipal; import org.shop.oauth.server.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.extern.slf4j.Slf4j; @Service @Slf4j public class UserServiceImpl implements UserService { @Autowired private UserEntityDao userDao; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { QueryWrapper<UserEntity> queryWrapper = new QueryWrapper<UserEntity>(); queryWrapper.eq("username", username); UserEntity userEntity = userDao.selectOne(queryWrapper); if (userEntity != null) { if (userEntity.getStatus() == 2) { throw new ShopException(ResultCode.ACCOUNTDISABLED.getMessage()); } else if (userEntity.getStatus() == 3) { throw new ShopException(ResultCode.ACCOUNTLOCKED.getMessage()); } else if (userEntity.getStatus() == 4) { throw new ShopException(ResultCode.ACCOUNTEXPIRED.getMessage()); } log.info("通过用户名: {} 获取user信息:{}",username,JSON.toJSONString(userEntity)); return new UserPrincipal(userEntity); } else { log.info("通过用户名: {} 没有找到对应的用户",username); throw new ShopException(ResultCode.USERNAMEORPASSWORDERROR.getMessage()); } } }
这里我们可以做一些粗略的判断,例如:用户查询不到,用户的状态不对等等。可以在这里做一些错误的异常处理。方便用户在认证的时候查询对应的错误信息。
以上就是自定义查询用户的代码逻辑介绍。
备注:
1、这里只有这个方法,通过用户名查询用户,如果是密码模式的时候,用户还需要传递密码,此时密码如果输入错误,那么在这里是无法进行判断的。
最后按照惯例,附上本案例的源码,登录后即可下载
还没有评论,来说两句吧...