SSM整合shiro、JWT

一、禁用shiro原有的session

**(目的是在使用前后端分离,移动端,小程序访问时候没有session)

1.首先自定义类继承DefaultWebSubjectFactory(注:此配置只用于**springboot中有用,在SSM框架中会报错,错误信息:session create ……disabled)

package com.datacraftman.PB.config;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.SubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSubjectFactory;

/**
 * @Author WangXuefeng
 * @Create 2020-07-25-14:28
 * @Description: 禁用session
 */
public class StatelessDefaultSubjectFactory extends DefaultWebSubjectFactory {


    @Override
    public Subject createSubject(SubjectContext context) {
        //不创建session
        context.setSessionCreationEnabled(false);
        return super.createSubject(context);
    }
}
2.进行spring-shiro.xml配置
配置如下两个配置防止报错(即:报错信息是session没有能力的错误)
<!--解决报错,组装默认的subjectDAO-->
<bean id="subjectDAO" class="org.apache.shiro.mgt.DefaultSubjectDAO">
    <property name="sessionStorageEvaluator" ref="sessionStorageEvaluator"/>
</bean>
<bean id="sessionStorageEvaluator" class="org.apache.shiro.mgt.DefaultSessionStorageEvaluator">
    <property name="sessionStorageEnabled" value="false"/>
</bean>
同时还要配置以下两个配置防止报错
<!-- 相当于调用SecurityUtils.setSecurityManager(securityManager) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
    <property name="arguments" ref="securityManager"/>
</bean>

<!-- 禁用掉会话调度器 -->
<bean id="sessionManager" class="org.apache.shiro.session.mgt.DefaultSessionManager">
    <property name="sessionValidationSchedulerEnabled" value="true"/>
</bean>

(切记:如果还报错那种的session disabled的错误一定是这几个配置没有放进SecurityManager容器中,需要在SecurityManager中注入上面的两个配置进去,如下)

<!--安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <!--注入认证授权realm-->
    <property name="realm" ref="customRealm"/>
    <!-- 在安全管理器中注入缓存管理器 -->
    <!--        <property name="cacheManager" ref="cacheManager"/>-->


    <!--解决报错,组装默认的subjectDAO-->
    <property name="subjectDAO" ref="subjectDAO"/>
    <!-- 禁用掉会话调度器 -->
    <property name="sessionManager" ref="sessionManager"/>

</bean>
引入spring-shiro.xml中(ssm不用引入)
<!--配置禁用session-->
<bean id="statelessDefaultSubjectFactory" class="com.datacraftman.PB.config.StatelessDefaultSubjectFactory">(springboot)

二、SHIRO自定义拦截器

既然要整合JWT就要重写自定义的拦截器主要重写的shiro的两个方法

  1. onAccessDenied

  2. isAccessAllowed

isAccessAllowed方法return true会放行,return false则会调用onAccessDenied方法,如果发现返回true还有报错的话百分之90还是shiro配置的原因,那几个防止shiro配置session后报错的那几个配置。

这里用的JWT工具包写的工具类所以整合的代码如下:

package com.datacraftman.PB.filter;

import com.auth0.jwt.interfaces.Claim;
import com.datacraftman.PB.utils.JwtUtil;
import com.datacraftman.PB.vo.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * @Author WangXuefeng
 * @Create 2020-07-25-15:15
 * @Description: 自定义session拦截器
 */
public class NoSessionFilter extends AuthorizationFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        System.out.println("isAccessAllowed");
        //强转HttpServletRequest
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        //取token
        String token = httpServletRequest.getParameter("token");
        //判断token
        if("".equals(token) || token == null){
            return false;
        }
        //进行过期验证
        try {
            JwtUtil.verifyToken(token);
        } catch (Exception e) {
            return false;
        }
        //解析token
        Map<String, Claim> map = JwtUtil.parseToken(token);
        Claim userId = map.get("userId");
        //判断用户id
        if("".equals(userId.asInt()) || userId.asInt() == null){
            return false;
        }
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) {


        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setCharacterEncoding("utf-8");
        resp.setContentType("application/json; charset=utf-8");
        ObjectMapper mapper = new ObjectMapper();
        try {
            resp.getWriter().write(mapper.writeValueAsString(new Result("500",null,"未登录!")));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }


}
3.既然写完类不像springboot那么方便,我们还要将重写好的拦截器配进去以替换shiro默认的拦截器

首先将写好的拦截器注入spring-shiro容器中

<!--自定义拦截规则-->
<bean id="noSessionFilter" class="com.datacraftman.PB.filter.NoSessionFilter"></bean>

然后再ShiroFilterFactoryBean中引用自己写好的类替换原有的

<!--        引入自定的拦截器-->
        <property name="filters">
            <map>
                <entry key="jwt" value-ref="noSessionFilter"/>
            </map>
        </property>

最后如下就可以用自己的拦截器了

<!--shiro过滤器-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--注入安全管理器-->
        <property name="securityManager" ref="securityManager"/>
        <!--没有登录的时候,跳转到这个页面-->
<!--                <property name="loginUrl" value="/user/unauth"/>-->
<!--        &lt;!&ndash;无权限跳转页面&ndash;&gt;-->
<!--                <property name="unauthorizedUrl" value="/user/nopermission"/>-->

<!--        引入自定的拦截器-->
        <property name="filters">
            <map>
                <entry key="jwt" value-ref="noSessionFilter"/>
            </map>
        </property>

        <!--过滤器链,优先级从上往下-->
        <property name="filterChainDefinitions">
            <value>
                <!--anno表示不需要登录就可以访问-->
                /user/login = anon
                /user/unauth = anon
                /register/* = anon
                <!-- 验证码,可匿名访问 -->
                <!--                /validatecode.jsp** = anon-->
                <!--                /webapp/** = anon-->
                <!--                &lt;!&ndash;/user/createCode= anon&ndash;&gt;-->
                <!--                &lt;!&ndash;auhtc表示需要认证才能访问&ndash;&gt;-->
                <!--                /user/readUser = authc,perms[/readUser]  &lt;!&ndash;perms表示拥有此权限才能访问&ndash;&gt;-->
                <!--                /user/readBook = authc,perms[vip]-->
                /user/* = jwt <!—使用自定义拦截器-->
                /** = jwt
            </value>
        </property>
    </bean>
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值