SpringBoot SpringSecurity知识点

明确三个接口GrantedAuthority(角色权限) UserDetails (用户信息) UserDetailsService(获取用户信息和用户权限)

角色表DO实现GrantedAuthority接口:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RoleInfo implements GrantedAuthority{
	private static final long serialVersionUID = 7088351652237386029L;

	private Long roleId;
	
	private String roleName;
	
	private String roleDesc;

	@Override
	public String getAuthority() {
		return roleName;
	}
}

MyUserDetails实现UserDetails接口,里面包含用户信息和用户角色信息

@Data
@AllArgsConstructor 
@NoArgsConstructor 
public class MyUserDetails implements UserDetails {
    private UserInfo userInfo;
    private List<RoleInfo> roleList;
//    private List<SimpleGrantedAuthority> authority;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        //返回当前用户的权限
    	return roleList;
//    	return roleList.stream()
//                .filter(role -> role.getRoleName()!=null)
//                .map(role ->new SimpleGrantedAuthority(role.getRoleName()))
//                .collect(Collectors.toList());
    }

    @Override
    public String getPassword() {
        return userInfo.getUserPassword();
    }

    @Override
    public String getUsername() {
        return userInfo.getUserName();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

实现UserDetailService,重写loadUserByUsername方法用来获取UserDetail

@Component	
public class UserDetailServiceImp implements UserDetailsService {
	@Autowired
	UserInfoService userInfoService;
	
	@Autowired
	UserRoleService userRoleService;

	@Override
	public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException {
		// 获取登录用户信息
		UserInfo admin = userInfoService.selectById(userId);
		if (admin != null) {
			List<RoleInfo> roleList = userRoleService.getRoleListByUserId(Long.valueOf(userId));
			return new MyUserDetails(admin, roleList);//自定义的UserDetailService
		}
		throw new UsernameNotFoundException("用户名或密码错误");
	}
}

spring security的filter调用链:

在这里插入图片描述
在这里插入图片描述
第二张图标蓝的JwtAuthenticationTokenFilter是自定义的filter
最后一个FilterSecurityInterceptor是SpringSecurity用来进行权限认证的filter,用来检测JwtAuthenticationTokenFilter传过来的UsernamePasswordAuthenticationToken是否"authorized"、检查用户角色是否有权限(上文中的RoleInfo)及其他检测。

FilterSecurityInterceptor继承自AbstractSecurityInterceptor,role认证主要看AbstractSecurityInterceptor中的beforeInvocation方法,beforeInvocation()方法内调用了accessDecisionManager接口(AffirmativeBased继承并提供方法)的decide()方法(看源码去)在这里插入图片描述
AffirmativeBased的decide方法:

public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {
		int deny = 0;

		for (AccessDecisionVoter voter : getDecisionVoters()) {
			int result = voter.vote(authentication, object, configAttributes);

			if (logger.isDebugEnabled()) {
				logger.debug("Voter: " + voter + ", returned: " + result);
			}

			switch (result) {
			case AccessDecisionVoter.ACCESS_GRANTED:
				return;

			case AccessDecisionVoter.ACCESS_DENIED:
				deny++;

				break;

			default:
				break;
			}
		}

		if (deny > 0) {
			throw new AccessDeniedException(messages.getMessage(
					"AbstractAccessDecisionManager.accessDenied", "Access is denied"));
		}

		// To get this far, every AccessDecisionVoter abstained
		checkAllowIfAllAbstainDecisions();
	}

大体意思就是用投票器的方式,多个投票器有一个投票不成功(result=-1),就返回403,access denied。

发布了10 篇原创文章 · 获赞 0 · 访问量 127

猜你喜欢

转载自blog.csdn.net/m178643/article/details/103095275
今日推荐