spring-boot: 2.1.4.RELEASE
spring-security-oauth3: 2.3.3.RELEASE (If you want to use the source code, do not change this version number at will, because The writing method from 2.4 up is different)
mysql: 5.7
Only postman is used for testing here, and the front-end page is not used for docking yet. Next There will be a page display for the permission allocation of the version role menu
1. Access the open interface http://localhost:7000/open/hello
2 . Access the protected interface http://localhost:7000/admin/user/info
## without a token. 3. Obtain the token after logging in, bring the token to access, and return successfully. The current login user information realizeoauth3 has four modes in total, which will not be explained here. Yes, I searched online and found the same thingBecause now we only consider unilateral applications, we use the password mode. There will be an article on SpringCloud Oauth3 later, gateway authenticationLet’s talk about a few points1. Interceptor configuration dynamic permissions Create a new MySecurityFilter class, inherit AbstractSecurityInterceptor, and implement the Filter interfaceInitialization, custom access decision manager@PostConstruct public void init(){ super.setAuthenticationManager(authenticationManager); super.setAccessDecisionManager(myAccessDecisionManager); }
@Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.mySecurityMetadataSource; }
/** * 获得当前请求所需要的角色 * @param object * @return * @throws IllegalArgumentException */ @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { String requestUrl = ((FilterInvocation) object).getRequestUrl(); if (IS_CHANGE_SECURITY) { loadResourceDefine(); } if (requestUrl.indexOf("?") > -1) { requestUrl = requestUrl.substring(0, requestUrl.indexOf("?")); } UrlPathMatcher matcher = new UrlPathMatcher(); List<Object> list = new ArrayList<>(); //无需权限的,直接返回 list.add("/oauth/**"); list.add("/open/**"); if(matcher.pathsMatchesUrl(list,requestUrl)) return null; Set<String> roleNames = new HashSet(); for (Resc resc: resources) { String rescUrl = resc.getResc_url(); if (matcher.pathMatchesUrl(rescUrl, requestUrl)) { if(resc.getParent_resc_id() != null && resc.getParent_resc_id().intValue() == 1){ //默认权限的则只要登录了,无需权限匹配都可访问 roleNames = new HashSet(); break; } Map map = new HashMap(); map.put("resc_id", resc.getResc_id()); // 获取能访问该资源的所有权限(角色) List<RoleRescDTO> roles = roleRescMapper.findAll(map); for (RoleRescDTO rr : roles) roleNames.add(rr.getRole_name()); } } Set<ConfigAttribute> configAttributes = new HashSet(); for(String roleName:roleNames) configAttributes.add(new SecurityConfig(roleName)); log.debug("【所需的权限(角色)】:" + configAttributes); return configAttributes; }
@Override public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if(configAttributes == null){ //属于白名单的,不需要权限 return; } Iterator<ConfigAttribute> iterator = configAttributes.iterator(); while (iterator.hasNext()){ ConfigAttribute configAttribute = iterator.next(); String needPermission = configAttribute.getAttribute(); for (GrantedAuthority ga: authentication.getAuthorities()) { if(needPermission.equals(ga.getAuthority())){ //有权限,可访问 return; } } } throw new AccessDeniedException("没有权限访问"); }
@Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.authenticationEntryPoint(authenticationEntryPoint) //token失效或没携带token时 .accessDeniedHandler(requestAccessDeniedHandler); //权限不足时 }
protected User user; public SecurityUser(User user) { this.user = user; } public User getUser() { return user; }
protected User getUser() { try { SecurityUser userDetails = (SecurityUser) SecurityContextHolder.getContext().getAuthentication() .getPrincipal(); User user = userDetails.getUser(); log.debug("【用户:】:" + user); return user; } catch (Exception e) { } return null; }
@Service public class TokenUserDetailsService implements UserDetailsService{ @Autowired private LoginService loginService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = loginService.loadUserByUsername(username); //这个我们拎出来处理 if(Objects.isNull(user)) throw new UsernameNotFoundException("用户名不存在"); return new SecurityUser(user); } }
@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); }
@Override public User loadUserByUsername(String username){ log.debug(username); Map map = new HashMap(); map.put("username",username); map.put("is_deleted",-1); User user = userMapper.findByUsername(map); if(user != null){ map = new HashMap(); map.put("user_id",user.getUser_id()); //查询用户的角色 List<UserRoleDTO> userRoles = userRoleMapper.findAll(map); user.setRoles(listRoles(userRoles)); //权限集合 Collection<? extends GrantedAuthority> authorities = merge(userRoles); user.setAuthorities(authorities); return user; } return null; }
The above is the detailed content of How does SpringBoot integrate SpringSecurityOauth2 to implement dynamic permission issues for authentication?. For more information, please follow other related articles on the PHP Chinese website!