SpringBoot整合SpringSecurityOauth2实现鉴权-动态权限

SpringBoot整合SpringSecurityOauth2实现鉴权-动态权限

写在前面

思考:为什么需要鉴权呢?

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

准备

spring-boot:2.1.4.RELEASE

spring-security-oauth2:2.3.3.RELEASE(如果要使用源码,不要随意改动这个版本号,因为2.4往上的写法不一样了)

mysql:5.7

效果展示

这边只用了postman做测试,暂时未使用前端页面来对接,下个版本角色菜单权限分配的会有页面的展示

1、访问开放接口 http://localhost:7000/open/hello

2、不带token访问受保护接口 http://localhost:7000/admin/user/info

3、登录后获取token,带上token访问,成功返回了当前的登录用户信息

实现

oauth2一共有四种模式,这边就不做讲解了,网上搜一搜,千篇一律

因为现在只考虑做单方应用的,所以使用的是密码模式。

后面会出一篇SpringCloud+Oauth2的文章,网关鉴权

讲一下几个点吧

1、拦截器配置动态权限

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

初始化,自定义访问决策管理器

@PostConstruct public void init(){ super.setAuthenticationManager(authenticationManager); super.setAccessDecisionManager(myAccessDecisionManager); }

自定义 过滤器调用安全元数据源

@Overridepublic SecurityMetadataSource obtainSecurityMetadataSource() { return this.mySecurityMetadataSource;}

先来看一下自定义过滤器调用安全元数据源的核心代码

以下代码是用来获取到当前请求进来所需要的权限(角色)

/** * 获得当前请求所需要的角色 * @param object * @return * @throws IllegalArgumentException */ @Override public Collection 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 list = new ArrayList(); //无需权限的,直接返回 list.add(“/oauth/**”); list.add(“/open/**”); if(matcher.pathsMatchesUrl(list,requestUrl)) return null; Set 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 roles = roleRescMapper.findAll(map); for (RoleRescDTO rr : roles) roleNames.add(rr.getRole_name()); } } Set 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 configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if(configAttributes == null){ //属于白名单的,不需要权限 return; } Iterator 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://blog.csdn.net/Pastxu/article/details/124538364

@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 userRoles = userRoleMapper.findAll(map); user.setRoles(listRoles(userRoles)); //权限集合 Collection authorities = merge(userRoles); user.setAuthorities(authorities); return user; } return null; }

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

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

数据库文件在这

点个小赞呗

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年6月21日
下一篇 2022年6月21日

相关推荐

  • 除了魔域,网龙营收增长乏力

    编辑 | 于斌 出品 | 潮起网「于见专栏」 网龙,即便手里有着英雄无敌、地下城守护者、变形金刚之类的金字招牌;还买了虚幻3引擎,还尝试了各种游戏类型,比如武侠OL,仿CF的3D设…

    2022年8月5日
  • 618手机销量第一又是它,已成为追求性能、好用的第一选择

    一年一度的六一八,是智能手机销量的关键时期,也是用户换手机的好时机,因为这个时候,手机之间竞争激烈,价格优惠力度很大,性价比最高。 六一八的手机销量也是网友关注的重点,在国产手机品…

    2022年6月14日
  • 赵丽颖 2022年04月30日新消息

    赵丽颖 赵丽颖 2022年04月30日新消息 赵丽颖为智齿拍证件照 被曝和冯绍峰将再度合作后 越来越接地气 12位白衣美人 鞠婧祎杨幂赵丽颖刘亦菲唐嫣杨颖谁仙气飘飘 赵丽颖为了保全…

    2022年5月11日
  • 《雪中悍刀行2》将启,张若昀携3大主演回归,青鸟新人选遭抵制

    《雪中悍刀行》是张若昀继《庆余年》之后,再次领衔主演的一部古装大男主剧,该剧由烽火戏诸侯笔下同名小说改编而来,由宋晓飞执导,李庚希、胡军、高伟光、张天爱等人主演。 《雪中悍刀行2》…

    2022年9月13日
  • 你同意吗:发射地球的位置,邀请外星人回信

    一群国际科学家正在准备把地球变成银河系的灯塔,向外星人广播地球的位置,并且邀请他们给我们回信。这不是科幻小说,科学家正在认真评估这个计划,要是顺利的话,他们可能会利用中国的天眼射电…

    2022年8月16日
  • 这些细节决定成败(社群运营怎么做)

    今天分享的是如何做好社群运营?要做好哪些细节?做好社群运营需要掌握的要点 手机的出现让人与人之间的距离更近了,社群的出现让人心与人心的距离更近了。 当内容成为信息的携带者,社群成为…

    2022年10月19日
  • 《重生之门》张译评价王俊凯,只字不提演技,却精准戳中观众心窝

    连续4天斩获全网热度冠军,相关热搜话题引爆全网,不得不说张译、王俊凯主演的《重生之门》爆了! 该剧剧情紧凑、烧脑、刺激,几乎所有事都在观众的意料之外,完全不按你想的套路出牌,并且压…

    2022年5月11日
  • 花呗调整还款日当月生效吗 这个月的还要还吗?

    在如今,支付宝用户开通花呗以后,还款日一般都是固定的,但用户可以修改还款日,很多人对此的认识不多,那么花呗调整还款日当月生效吗?下文就来带大家了解一下。 花呗调整还款日后,一般是下…

    2022年9月3日
  • 孩子过度自恋?请父母检讨这三点

    据阿根廷布宜诺斯艾利斯经济新闻网8月14日报道,养育孩子,对世界各地的父母来说都是一项既充满爱又有难度的任务。很多时候,父母会在不自知的情况下将某些模式传递给自己的孩子,这些影响多…

    2022年8月23日
  • 电脑C盘清理垃圾和缓存的办法

    首先按下电脑键盘的win+R后,打开电脑的运行框输入代码%TEMP%后,点击确定,选择要清理的系统那些无用的缓存垃圾后,再按下电脑键盘的win+R后,打开电脑的运行框输入代码Cle…

    2022年8月21日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息