springboot整合security权限控制,springcloudoauth2权限控制

  springboot整合security权限控制,springcloudoauth2权限控制

  00-1010写在前面,为实现效果展示做准备。

  00-1010思考:为什么需要认证?

  系统开发上线后,API接口会暴露在互联网上,存在一定的安全风险,如爬虫、恶意访问等。所以我们需要对非开放API接口的用户进行认证,认证通过后再允许调用。

  

目录

弹簧靴:2.1.4 .版本

 

  春天-安全-OAuth 2: 2.3.3。发布(如果要用源代码,不要随意改这个版本号,因为2.4写的不一样)

  mysql:5.7

  00-1010上只使用了postman进行测试,暂时不使用前端页面进行对接。在下一版本中分配角色菜单权限时,将显示该页面。

  1.访问开放接口http://localhost 33607000/open/hello。

  2.不使用令牌访问受保护的接口http://localhost 33607000/admin/user/info

  3.登录后获取令牌,用令牌访问,成功返回当前登录用户信息。

  00-1010 OAuth 2有四种模式,这里就不解释了。网上搜一下,都是一样的。

  因为现在只考虑单方申请,所以使用密码模式。

  会有一篇关于SpringCloud Oauth2的文章,网关认证。

  谈几点。

  1.拦截器配置动态权限。

  创建一个新的MySecurityFilter类,继承AbstractSecurityInterceptor,并实现Filter接口。

  初始化和定制访问决策管理器

  @ post construct public void init(){ super . setauthenticationmanager(authenticationManager);super . setaccessdecisionmanager(myAccessDecisionManager);}自定义过滤器调用安全元数据源

  @ override public SecurityMetadataSource observicesecuritymetadatasource(){ return this . mysecuritymetadasource;}我们先来看看自定义过滤器调用安全元数据源的核心代码。

  以下代码用于获取当前请求所需的权限(角色)。

  /* * *获取当前请求所需的角色* @ param Object * @ return * @ throwsillegargumentexception */@ Override public CollectionConfigAttribute Get attributes(Object Object)throws IllegalArgumentException { String request URL=((filter invocation)Object)。getRequestUrl();if(IS _ CHANGE _ SECURITY){ loadresourcdefine();} if (requestUrl.indexOf(?))-1){ request URL=request URL . substring(0,requestUrl.indexOf(?)));} urlpath matcher matcher=new urlpath matcher();ListObject list=new ArrayList();//如果不需要权限,直接返回list . add(/oauth/* *);list . add(/open/* * );if(matcher . paths matches URL(list,requestUrl))返回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("没有权限访问"); }

2、自定义鉴权异常返回通用结果

 

  为什么需要这个呢,如果不配置这个,对于前端,后端来说都很难去理解鉴权失败返回的内容,还不能统一解读,废话不多说,先看看不配置和配置了的返回情况

  (1)未自定义前,没有携带token去访问受保护的API接口时,返回的结果是这样的

  

 

  (2)我们规定一下,鉴权失败的接口返回接口之后,变成下面这种了,是不是更利于我们处理和提示用户

  

 

  好了,来看一下是在哪里去配置的吧

  我们资源服务器OautyResourceConfig,重写下下面这部分的代码,来自定义鉴权异常返回的结果

  大伙可以参考下这个https:///article/131668.htm

  

@Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.authenticationEntryPoint(authenticationEntryPoint) //token失效或没携带token时 .accessDeniedHandler(requestAccessDeniedHandler); //权限不足时 }

 

  3、获取当前登录用户

  第一种:使用JWT携带用户信息,拿到token后再解析

  暂不做解释

  第二种:写一个SecurityUser实现UserDetails接口(这个工程中使用的是这一种)

  原来的只有UserDetails接口只有username和password,这里我们加上我们系统中的User

  

protected User user; public SecurityUser(User user) { this.user = user; } public User getUser() { return user; }

在BaseController,每个Controller都会继承这个的,在里面写给getUser()的方法,只要用户带了token来访问,我们可以直接获取当前登录用户的信息了

 

  

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; }

那么用户登录成功后,如何去拿到用户的角色集合等呢,这里面就要实现UserDetailsService接口了

 

  

 

  

@Servicepublic 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); }}

然后在我们的安全配置类中设置UserDetailsService为上面的我们自己写的就行

 

  

@Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); }

最后我们只需要在loginService里面实现我们的方法就好,根据我们的实际业务处理判断该用户是否存在等

 

  

@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; }

大功告成啦,赶紧动起手来吧!

 

  附上源码地址:https://gitee.com/jae_1995/spring-boot-oauth2

  数据库文件在这

  

 

  到此这篇关于SpringBoot整合SpringSecurityOauth2实现鉴权-动态权限的文章就介绍到这了,更多相关SpringBoot整合SpringSecurityOauth2内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: