array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 springboot结合jwt实现权限认证 - 爱码网

1.什么是JWT

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

2.优点

体积小、传输快

支持跨域授权,因为跨域无法共享cookie

分布式系统中,很好地解决了单点登录问题

3.使用场景

1. 认证,这是比较常见的使用场景,只要用户登录过一次系统,之后的请求都会包含签名出来的token,通过token也可以用来实现单点登录。

2. 交换信息,通过使用**对来安全的传送信息,可以知道发送者是谁、放置消息被篡改。

4.项目克隆地址(以下过程代码简写,可自行克隆代码查看实现过程,这个框架是我自己搭建的,里边已经集成了很多东西,喜欢的可以研究研究,都是比较常用的技术,有什么问题也可以评论,看到会回复,账号密码 admin   admin)

ssh://[email protected]:29418/goudan.git

5.集成过程

(1)导入sql表,我把sql文件放在下图所示位置

springboot结合jwt实现权限认证

sql文件

(2)添加依赖

springboot结合jwt实现权限认证

依赖

(3)主体有5个文件需要添加,分别是shiroConfig、OAuth2Filer配置、OAuth2Realm、OAuth2Token、TokenGenerator

3.1 shiroConfig

springboot结合jwt实现权限认证

shiroConfig

具体代码如下

/**

* @program: xiaowu

* @description: Shiro配置

* @author: Wu

* @create: 2020-08-29 09:46

**/

@Configuration

public class ShiroConfig {

@Bean("sessionManager")

public SessionManagersessionManager(){

DefaultWebSessionManager sessionManager =new DefaultWebSessionManager();

        sessionManager.setSessionValidationSchedulerEnabled(true);

        sessionManager.setSessionIdCookieEnabled(true);

        return sessionManager;

    }

@Bean("securityManager")

public SecurityManagersecurityManager(OAuth2Realm oAuth2Realm, SessionManager sessionManager) {

DefaultWebSecurityManager securityManager =new DefaultWebSecurityManager();

        securityManager.setRealm(oAuth2Realm);

        securityManager.setSessionManager(sessionManager);

        return securityManager;

    }

@Bean("shiroFilter")

public ShiroFilterFactoryBeanshirFilter(SecurityManager securityManager) {

ShiroFilterFactoryBean shiroFilter =new ShiroFilterFactoryBean();

        shiroFilter.setSecurityManager(securityManager);

        //oauth过滤

        Map filters =new HashMap<>();

        filters.put("oauth2", new OAuth2Filter());

        shiroFilter.setFilters(filters);

        Map filterMap =new LinkedHashMap<>();

        filterMap.put("/druid/**", "anon");

        filterMap.put("/app/**", "anon");

        filterMap.put("/login", "anon");

        filterMap.put("/**", "oauth2");

        shiroFilter.setFilterChainDefinitionMap(filterMap);

        return shiroFilter;

    }

@Bean("lifecycleBeanPostProcessor")

public LifecycleBeanPostProcessorlifecycleBeanPostProcessor() {

return new LifecycleBeanPostProcessor();

    }

@Bean

    public DefaultAdvisorAutoProxyCreatordefaultAdvisorAutoProxyCreator() {

DefaultAdvisorAutoProxyCreator proxyCreator =new DefaultAdvisorAutoProxyCreator();

        proxyCreator.setProxyTargetClass(true);

        return proxyCreator;

    }

@Bean

    public AuthorizationAttributeSourceAdvisorauthorizationAttributeSourceAdvisor(SecurityManager securityManager) {

AuthorizationAttributeSourceAdvisor advisor =new AuthorizationAttributeSourceAdvisor();

        advisor.setSecurityManager(securityManager);

        return advisor;

    }

}

3.2  OAuth2Filer  过滤器(oauth2是一种规范,springcloud有个springsecurity oauth2是实现,这里用的jwt)

springboot结合jwt实现权限认证

OAuth2Filer

具体代码如下

/**

* @program: xiaowu

* @description: oauth2过滤器

* @author: Wu

* @create: 2020-08-29 10:09

**/

public class OAuth2Filterextends AuthenticatingFilter {

@Override

    protected AuthenticationTokencreateToken(ServletRequest request, ServletResponse response)throws Exception {

//获取请求token

        String token = getRequestToken((HttpServletRequest) request);

        if(StringUtil.isBlank(token)){

return null;

        }

return new OAuth2Token(token);

    }

@Override

    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {

if(((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name())){

return true;

        }

return false;

    }

@Override

    protected boolean onAccessDenied(ServletRequest request, ServletResponse response)throws Exception {

//获取请求token,如果token不存在,直接返回401

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        String token = getRequestToken((HttpServletRequest) request);

        if(StringUtil.isBlank(token)){

HttpServletResponse httpResponse = (HttpServletResponse) response;

            httpResponse.setHeader("Access-Control-Allow-Credentials", "true");

            httpResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));

            JSONObject json =new JSONObject();

            json.put("code", "401");

            json.put("msg", "invalid token");

            httpResponse.getWriter().print(json);

return false;

        }

return executeLogin(request, response);

    }

@Override

    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {

HttpServletResponse httpResponse = (HttpServletResponse) response;

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;

        httpResponse.setContentType("application/json;charset=utf-8");

        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");

        httpResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));

        try {

//处理登录失败的异常

            Throwable throwable = e.getCause() ==null ? e : e.getCause();

            JSONObject json =new JSONObject();

            json.put("code", "401");

            json.put("msg", throwable.getMessage());

            httpResponse.getWriter().print(json);

        }catch (IOException e1) {

}

return false;

    }

/**

    * 获取请求的token

*/

    private StringgetRequestToken(HttpServletRequest httpRequest){

//从header中获取token

        String token = httpRequest.getHeader("token");

        //如果header中不存在token,则从参数中获取token

        if(StringUtil.isBlank(token)){

token = httpRequest.getParameter("token");

        }

return token;

    }

}

3.3 OAuth2Realm配置(这个里面可以设置角色、权限和认证信息)

springboot结合jwt实现权限认证

OAuth2Realm

具体代码如下

/**

* @program: xiaowu

* @description: 认证

* @author: Wu

* @create: 2020-08-29 10:18

**/

@Component

public class OAuth2Realmextends AuthorizingRealm {

@Autowired

    private ManagerServicemanagerService;

    @Override

    public boolean supports(AuthenticationToken token) {

return tokeninstanceof OAuth2Token;

    }

/**

    * 授权(验证权限时调用, 控制role 和 permissins时使用)

*/

    @Override

    protected AuthorizationInfodoGetAuthorizationInfo(PrincipalCollection principals) {

ManagerInfo manager = (ManagerInfo)principals.getPrimaryPrincipal();

        Integer managerId = manager.getManagerId();

        SimpleAuthorizationInfo info =new SimpleAuthorizationInfo();

        // 模拟权限和角色

        Set permsSet =new HashSet<>();

        Set roles =new HashSet<>();

        if (managerId ==1) {

// 超级管理员-权限

            permsSet.add("delete");

            permsSet.add("update");

            permsSet.add("view");

            roles.add("admin");

        }else {

// 普通管理员-权限

            permsSet.add("view");

            roles.add("test");

        }

info.setStringPermissions(permsSet);

        info.setRoles(roles);

        return info;

    }

/**

    * 认证(登录时调用)

*/

    @Override

    protected AuthenticationInfodoGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException {

String accessToken = (String) token.getPrincipal();

        //根据accessToken,查询用户信息

        ManagerToken managerToken =managerService.queryByToken(accessToken);

        //token失效

        SimpleDateFormat sm =new SimpleDateFormat("yyyyMMddHHmmss");

        Date expireTime;

        boolean flag =true;

        try {

expireTime    = sm.parse(managerToken.getExpireTime());

            flag = managerToken ==null || expireTime.getTime() < System.currentTimeMillis();

        }catch (ParseException e) {

e.printStackTrace();

        }

if(flag){

throw new IncorrectCredentialsException("token失效,请重新登录");

        }

//查询用户信息

        ManagerInfo managerInfo =managerService.getManagerInfo(managerToken.managerId);

        //账号锁定

        // if(managerInfo.getStatus() == 0){

        //    throw new LockedAccountException("账号已被锁定,请联系管理员");

// }

        SimpleAuthenticationInfo info =new SimpleAuthenticationInfo(managerInfo, accessToken, getName());

        return info;

    }

}

3.4 OAuth2Token设置

springboot结合jwt实现权限认证

OAuth2Token

3.5 TokenGenerator, 生成token

springboot结合jwt实现权限认证

TokenGenerator

具体代码

/**

* @program: xiaowu

* @description: 生成token

* @author: Wu

* @create: 2020-08-29 10:26

**/

public class TokenGenerator {

public static StringgenerateValue() {

return generateValue(UUID.randomUUID().toString());

    }

private static final char[]hexCode ="0123456789abcdef".toCharArray();

    public static StringtoHexString(byte[] data) {

if (data ==null) {

return null;

        }

StringBuilder r =new StringBuilder(data.length *2);

        for (byte b : data) {

r.append(hexCode[(b >>4) &0xF]);

            r.append(hexCode[(b &0xF)]);

        }

return r.toString();

    }

public static StringgenerateValue(String param) {

try {

MessageDigest algorithm = MessageDigest.getInstance("MD5");

            algorithm.reset();

            algorithm.update(param.getBytes());

            byte[] messageDigest = algorithm.digest();

            return toHexString(messageDigest);

        }catch (Exception e) {

throw new RuntimeException("生成Token失败", e);

        }

}

}

4.测试(这里以登录接口验证为例)

springboot结合jwt实现权限认证

登录接口

实现层代码

springboot结合jwt实现权限认证

实现层

mapper文件还有这种写法(头一次见,以前都是在业务代码里写的)

springboot结合jwt实现权限认证

xml文件

postman测试

springboot结合jwt实现权限认证

测试

springboot结合jwt实现权限认证

mysql

接口权限已经完成,剩下的就是根据过期时间的业务代码,当然这个token加密算法比较简单,我们可以更换加密算法,这以后再完善

如果觉得对你有帮助,可以搜索公众号  ‘蛋皮皮’   关注作者支持一下,每天会不定时回复留言(有任何问题都可以留言哦)。

                                springboot结合jwt实现权限认证

相关文章: