博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
shiro 整合
阅读量:3954 次
发布时间:2019-05-24

本文共 13550 字,大约阅读时间需要 45 分钟。

package com.itshare.video.common.shiro;import com.itshare.video.common.shiro.realm.JwtRealm;import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;import org.apache.shiro.mgt.DefaultSubjectDAO;import org.apache.shiro.spring.LifecycleBeanPostProcessor;import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.DependsOn;import javax.servlet.Filter;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map;/** * @Author lyr * @create 2020/10/25 11:47 */@Configurationpublic class JwtShiroConf {
public static final String JWT_FILTER_RULE = "jwt_rule"; /** * 配置使用自定义Realm,关闭Shiro自带的session * 详情见文档 http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29 * @return org.apache.shiro.web.mgt.DefaultWebSecurityManager * @author dolyw.com * @date 2018/8/31 10:55 */ @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") @Bean("securityManager") public DefaultWebSecurityManager defaultWebSecurityManager() {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); // 使用自定义Realm defaultWebSecurityManager.setRealm(new JwtRealm()); // 关闭Shiro自带的session DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO(); DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator(); defaultSessionStorageEvaluator.setSessionStorageEnabled(false); subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator); defaultWebSecurityManager.setSubjectDAO(subjectDAO); // 设置自定义Cache缓存 return defaultWebSecurityManager; } /** * 添加自己的过滤器,自定义url规则 * Shiro自带拦截器配置规则 * rest:比如/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等 * port:比如/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数 * perms:比如/admins/user/**=perms[user:add:*],perms参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,比如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法 * roles:比如/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,比如/admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。//要实现or的效果看http://zgzty.blog.163.com/blog/static/83831226201302983358670/ * anon:比如/admins/**=anon 没有参数,表示可以匿名使用 * authc:比如/admins/user/**=authc表示需要认证才能使用,没有参数 * authcBasic:比如/admins/user/**=authcBasic没有参数表示httpBasic认证 * ssl:比如/admins/user/**=ssl没有参数,表示安全的url请求,协议为https * user:比如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查 * 详情见文档 http://shiro.apache.org/web.html#urls- * @param securityManager * @return org.apache.shiro.spring.web.ShiroFilterFactoryBean * @author dolyw.com * @date 2018/8/31 10:57 */ @Bean("shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); // 添加自己的过滤器取名为jwt Map
filterMap = new HashMap<>(16); filterMap.put("jwt", new JwtFilter()); factoryBean.setFilters(filterMap); factoryBean.setSecurityManager(securityManager); // 自定义url规则使用LinkedHashMap有序Map LinkedHashMap
filterChainDefinitionMap = new LinkedHashMap
(16); // 登录接口放开 // filterChainDefinitionMap.put("/user/login", "anon"); // "/api/getToken","/api/login/**","/api/register/**" filterChainDefinitionMap.put("/api/login/email","anon"); filterChainDefinitionMap.put("/api/register/email","anon"); filterChainDefinitionMap.put("/api/login/**","anon"); filterChainDefinitionMap.put("/api/register/**","anon"); // 所有请求通过我们自己的JWTFilter filterChainDefinitionMap.put("/api/**", "jwt"); factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return factoryBean; } /** * 下面的代码是添加注解支持 */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); // 强制使用cglib,防止重复代理和可能引起代理出错的问题,https://zhuanlan.zhihu.com/p/29161098 defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor(); } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; }}
package com.itshare.video.common.shiro.realm;import com.itshare.video.common.shiro.entity.JwtToken;import lombok.extern.slf4j.Slf4j;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.subject.Subject;/** * @Author lyr * @create 2020/10/25 11:36 */@Slf4jpublic class JwtRealm extends AuthorizingRealm {
@Override public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken; } /** * 登录验证 * * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// if (!(authenticationToken instanceof JwtToken)) {
// return null; // } JwtToken token = ((JwtToken) authenticationToken); // System.out.println(token); // String id = token.getData().get("id").toString(); return new SimpleAuthenticationInfo(token, token, getName()); // if(token.isCanPass()) {
// log.info("验证通过"); // return new SimpleAuthenticationInfo(token,token,getName()); } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo per = new SimpleAuthorizationInfo(); // SecurityUtils.getSubject() --> 获取当前用户,和 获取对应的 token的信息 Subject subject = SecurityUtils.getSubject(); String id = subject.getPrincipal().toString(); log.info("用户id授权 {}",id); //进行授权操作 // per.addStringPermission("user:add"); return per; }}
package com.itshare.video.common.shiro;import cn.hutool.core.util.StrUtil;import com.itshare.video.common.core.constant.enums.ApiInfo;import com.itshare.video.common.dto.Result;import com.itshare.video.common.shiro.entity.JwtToken;import com.itshare.video.common.util.JwtAdapter;import com.itshare.video.common.web.WebUtil;import lombok.extern.slf4j.Slf4j;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authz.UnauthorizedException;import org.apache.shiro.subject.Subject;import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;import org.apache.shiro.web.util.WebUtils;import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * @Author lyr * @create 2020/10/25 10:00 */@Slf4jpublic class JwtFilter extends BasicHttpAuthenticationFilter {
// public static final String header = "token"; // public static final String ATTR_TOKEN = "___token_jwt"; @Override protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; //options 请求,直接放行 if (req.getMethod().equals(RequestMethod.OPTIONS.name())) {
res.setStatus(org.springframework.http.HttpStatus.OK.value()); return false; } return super.preHandle(request, response); } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws UnauthorizedException {
//判断请求的请求头是否带上 "Token" //如果存在,则进入 executeLogin 方法执行登入,检查 token 是否正确 try {
return executeLogin(request, response); } catch (Exception e) {
return false; } // return false; //如果请求头不存在 Token,则可能是执行登陆操作或者是游客状态访问,无需检查 token,直接返回 true } /** * 阻止自动重定向 * @param request * @param response * @return * @throws IOException */ @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
// Subject subject = this.getSubject(request, response); // if (subject.getPrincipal() == null) {
// this.saveRequestAndRedirectToLogin(request, response); // } else {
// String unauthorizedUrl = this.getUnauthorizedUrl(); // if (StringUtils.hasText(unauthorizedUrl)) {
// WebUtils.issueRedirect(request, response, unauthorizedUrl); // } else {
// WebUtils.toHttp(response).sendError(401); // } // } return false; } @Override protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
String token = WebUtils.toHttp(request).getHeader("token"); log.info("token {}",token); if (null == token || StrUtil.isBlank(token)) {
//直接将 no——token 返回给前端 WebUtil.renderJson((HttpServletResponse) response, Result.of(ApiInfo.NO_TOKEN)); return false; } JwtToken jwtToken = JwtUtils.decodeJwtToken(token); try {
request.setAttribute("id",jwtToken.getData().get("id")); request.setAttribute("role",jwtToken.getData().get("role")); log.info("token {}",jwtToken); //交给 realm 进行判断,并且返回 getSubject(request, response).login(jwtToken); log.info("验证通过 "); return true; } catch (AuthenticationException ex) {
log.info("出现异常了 {}",ex.getMessage()); if (JwtAdapter.JWTCode.OVERDUE.equals(jwtToken.getJwtCode())) {
// WebUtil.renderJson((HttpServletResponse) response, Result.of(ApiInfo.TOKEN_EXPIRED)); } else {
WebUtil.renderJson((HttpServletResponse) response, Result.of(ApiInfo.NO_TOKEN)); } return false; } }}

jwt

package com.itshare.video.common.shiro.entity;import com.itshare.video.common.util.JwtAdapter;import io.jsonwebtoken.Claims;import io.jsonwebtoken.JwtHandlerAdapter;import lombok.Data;import org.apache.shiro.authc.AuthenticationToken;/** * @Author lyr * @create 2020/10/25 9:48 */@Datapublic class JwtToken implements AuthenticationToken {
/** * token 内容 */ private String token; /** * jwt校验结果 */ private JwtAdapter.JWTCode jwtCode; /** * 解密结果 */ private Claims data; /** * 是否可以通过 */ private boolean canPass; @Override public Object getPrincipal() {
return this; } @Override public Object getCredentials() {
return this; } /** * @return token 过期 */ public boolean isExpire() {
return JwtAdapter.JWTCode.OVERDUE.equals(jwtCode); } /** * @return 校验失败 */ public boolean isCheckFail() {
return JwtAdapter.JWTCode.ERROR.equals(jwtCode); } /** * @return 校验成功 */ public boolean isSuccess() {
return JwtAdapter.JWTCode.SUCCESS.equals(jwtCode); }}

接口授权

@Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo per = new SimpleAuthorizationInfo(); // SecurityUtils.getSubject() --> 获取当前用户,和 获取对应的 token的信息 Subject subject = SecurityUtils.getSubject(); // String id = subject.getPrincipal().toString(); // log.info("用户id授权 {}",id); JwtToken jwtToken = (JwtToken) subject.getPrincipal(); String role = jwtToken.getData().get("role").toString(); if("1".equals(role)) {
per.addRole(Role.admin); }else if("2".equals(role)) {
per.addRole(Role.teacher); }else{
per.addRole(Role.student); } //进行授权操作 // per.addStringPermission("user:add"); return per; }

转载地址:http://kkyzi.baihongyu.com/

你可能感兴趣的文章
等待队列学习笔记
查看>>
MTK G-sensor
查看>>
linux工作队列
查看>>
Linux工作队列的使用
查看>>
linux kernel 工作队列
查看>>
移植Android 到mini2440
查看>>
Linux 进程调度原理
查看>>
globalfifo精彩问答
查看>>
ARM 启动过程
查看>>
ARM开发总结的小知识 Code,RO-data,RW-data,ZI-
查看>>
Linux驱动程序开发 - 设备驱动模型初探
查看>>
创业必看!
查看>>
Linux墙上时间
查看>>
怎样写 Linux LCD 驱动程序
查看>>
PADS Logic图文教程:更改切换元件
查看>>
PADS Logic图文教程:更改切换元件
查看>>
全面的framebuffer详解
查看>>
嵌入式Linux之我行——S3C2440上LCD驱动(FrameBuffer)实例开发讲解
查看>>
Linux Kernel and Android 休眠与唤醒
查看>>
android 系统关机,重启
查看>>