2021SC@SDUSC
JwtAuthenticationTokenFilter我们的项目中用到了很多关于Spring Security的内容,笔者虽然已经在学习Spring Security了,但是对于项目这种多个模块分离的Spring Security的使用流程还是不甚了解,今天我们就来理清一下项目中Spring Security 的逻辑。
首先我们看到位于security模块的 JwtAuthenticationTokenFilter 模块,他的 doFilterInternal 中关于当用户尚未认证时的处理逻辑为:
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); if (jwtTokenUtil.validateToken(authToken, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); LOGGER.info("authenticated user: {}", username); SecurityContextHolder.getContext().setAuthentication(authentication); } }
这里可以看到他调用了 userDetailsService 的 loadUserByUsername 方法。但是笔者却发现 security 模块中并没有对应的 userDetailService 的实现类,于是笔者猜测,关于 userDetailService 的实现类应该是每一个需要 security 的模块自己实现的。
我们转到 doc 模块下。
EditorUserDetailsServiceImpl可以看到这个模块中出现了对应的 UserDetailService 的实现类,我们观察他的 loadUserByUsername 方法的实现:
@Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { UmsUser user = userRepository.findByUsername(username).get(0); ListauthorityList = new ArrayList<>(); /// ========================= List editorRoleForUserVos = authorityService.selectRoleForUser(user.getUid()); /// ========================= editorRoleForUserVos.forEach( role -> { authorityList.add(new SimpleGrantedAuthority(role.getRole_name())); }); return new EditorUserDetails(user, authorityList); }
可以看到,这个方法中的关键 *** 作是
ListeditorRoleForUserVos = authorityService.selectRoleForUser(user.getUid());
调用了 authorityService 的 selectRoleForUser 方法
我们需要找到 authorityService 的实现类。
EditorAuthorityServiceImpl这个实现类中只实现了一个方法,也就是 selectRoleForUser :
@Override @Transactional public ListselectRoleForUser(Integer userId) { List resultList = new ArrayList<>(); StringBuilder sql_select_role_for_user = new StringBuilder(); sql_select_role_for_user .append("select ") .append("u.uid uid, u.username username, r.rid rid, r.`name` role_name, r.description role_description ") .append("from ") .append("ums_user u ") .append("left join ums_user_role_relation ur on u.uid = ur.uid ") .append("left join ums_role r on ur.rid = r.rid ") .append("where ") .append("u.uid = ") .append(userId); Query query = entityManager.createNativeQuery(sql_select_role_for_user.toString()); List list = query.unwrap(NativeQueryImpl.class) .setResultTransformer(Transformers.aliasToBean(EditorRoleForUserVo.class)) .getResultList(); list.forEach(item -> { resultList.add((EditorRoleForUserVo) item); }); return resultList; }
可以看到这里面有一个sql语句,我们首先观察一下他用到数据库,分别是
- usm_user
- ums_user_relation
- ums_role
实际上这部 *** 作可以得到user对应的role_name,并且返回一个list,表示这个user拥有的角色数。
查看了数据库后首先使用了正确的用户进行登录,获取到了token。
然后从JwtAuthenticationTokenFilter可得知,需要将这个token附到请求头中,并且需要将token前面加上一个特定的字符串。
进行了以上 *** 作后,请求成功:
@PreAuthorize("hasAnyRole('administrator_editor', 'author', 'administrator')") @RequestMapping(value = "/get_latest_id", method = RequestMethod.POST) public CommonResultgetLatestNewId() { Long latestId = service.getLatestId() + 1; return CommonResult.success(latestId); }
{ "code": 200, "message": " *** 作成功", "data": 1 }
分析完毕
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)