shiro框架小结

shiro是权限管理框架。权限管理是对用户的身份认证和访问权限验证。

shiro涉及的三个对象:

1)Subject:主体

访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;

2)Principal:身份信息

是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。

3)credential:凭证信息

只有主体自己知道的安全信息,如密码、证书等。

shiro执行逻辑

在这里插入图片描述

shiro与springmvc的集成

1.pom.xml引入

2.配置web.xml

 <!-- shiro 过滤器 start -->
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <!-- 设置true由servlet容器控制filter的生命周期 -->
    <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!-- shiro 过滤器 end -->

3.配置spring-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
                        http://www.springframework.org/schema/util
                        http://www.springframework.org/schema/util/spring-util-4.1.xsd">

    <description>权限配置</description>
    <!-- Realm实现 -->
    <bean id="userRealm" class="com.sdhsie.essos.lys.login.component.UserRealm">
        <property name="cachingEnabled" value="false"/>
    </bean>

    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="userRealm"/>
        <property name="cacheManager" ref="cacheManager"/>
    </bean>

    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>

    <!-- Shiro生命周期处理器-->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>
    </bean>

    <!-- 基于Form表单的身份验证过滤器 -->
    <bean id="formAuthenticationFilter" class="com.sdhsie.essos.lys.login.component.MyFormAuthenticationFilter">
        <property name="usernameParam" value="username"/>
        <property name="passwordParam" value="password"/>
        <property name="rememberMeParam" value="rememberMe"/>
    </bean>
    <bean id="rolesAuthorizFilter" class="com.sdhsie.essos.lys.login.component.MyRolesAuthorizationFilter"> </bean>

    <!-- Shiro的Web过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- shiro的核心安全接口 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 要求登录时的链接 -->
        <!--<property name="loginUrl" value="/login"/>-->
        <!-- 登陆成功后要跳转的连接 -->
        <!--<property name="successUrl" value="/" />-->
        <property name="filters">
            <util:map>  
                <entry key="authc" value-ref="formAuthenticationFilter"/>
                <entry key="roles" value-ref="rolesAuthorizFilter"/>
            </util:map>
        </property>
        <property name="filterChainDefinitions">
            <value>
                / = anon
                /app/ = anon
                /doLogin = anon
                /registerDriver = anon
                /app/**/*.js = anon
                /app/**/*.css = anon
                /app/**/*.gif = anon
                /app/**/*.png = anon
                /app/**/*.jpg = anon
                /jsp/**/*.jsp = anon
                /jsp/**/*.html = anon
                /**/noauth = anon
                /logout = anon
                /workinformtruckweb/**=roles[admin]
                /user/deleteUser/** = perms[USER:DELETE]
                /** = authc
            </value>
        </property>
    </bean>
</beans>

1)声明SecurityManager,注入自定义的realm。定义身份验证和权限授权。
2)声明Shiro的WEB过滤器,必须引入securityManager,WEB过滤器主要用于URL的访问控制,控制哪些URL需要权限控制,哪些不需要权限控制
anon:表示不需要权限控制
authc:表示需要登录后才能访问
roles[admin]: 表示有admin角色的才能访问
perms[USER:DELETE]:表示有USER:DELETE权限的才能访问
下面会具体代码说明roles和perms的赋值

4.自定义Realm

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserInfoService userInfoService;
    /**
     * 表示根据用户身份获取权限信息并授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        Set<String> roles = Sets.newHashSet();
        roles.add("超级管理员");
        authorizationInfo.setRoles(roles);
        return authorizationInfo;
    }

    /**
     * 表示获取身份验证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token){
        if(token.getPrincipal()==null || token.getCredentials()==null){
            return null;
        }

        UsernamePasswordToken upToken = (UsernamePasswordToken)token;
        String userName = upToken.getUsername();
        String psw = new String(upToken.getPassword());
        if(LoginController.PSW_FLAG.equals(psw)){

        }else{
            UserInfo userInfo = userInfoService.checkByUserName(userName);
            if(userInfo == null) {
                throw new UnknownAccountException();//没找到帐号
            }else{
                psw = userInfo.getPassword();
            }
        }

        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                userName,     //用户名
                psw,     //密码
                null,       //salt=username+salt
                getName()                   //realm name
        );

        return authenticationInfo;
    }

    @Override
    protected void assertCredentialsMatch(AuthenticationToken authcToken,
                                          AuthenticationInfo info) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

        super.assertCredentialsMatch(token, info);
    }
}

doGetAuthorizationInfo里给roles造了假数据

5.自定义登录验证过滤器

public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        Subject logUser = SecurityUtils.getSubject();
        //电脑版可使用cookie-session保持会话信息
        if(logUser.isAuthenticated()){
            return super.preHandle(request, response);
        }
        return super.preHandle(request, response);
    }

    //处理跨域问题
    public static void setResponse(HttpServletResponse res, HttpServletRequest req){
        //HttpServletResponse res = (HttpServletResponse) response;
        res.setHeader("Access-Control-Allow-Origin",req.getHeader("origin"));
        res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        res.setHeader("Access-Control-Max-Age", "3600");
        res.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
        res.setHeader("Access-Control-Allow-Credentials", "true");
    }

    //未登录访问被拒绝时调用
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        try {
            HttpServletRequest req = (HttpServletRequest)request;
            HttpServletResponse res = (HttpServletResponse)response;
//。。。。
        //返回false自己处理,不再使用shiro的filter
        return false;
    }
}

AccessControlFilter的onPreHandle调用isAccessAllowed和onAccessDenied

    public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);
    }

6.点击登陆请求的控制层

  public Object doLogin(String username, String password, String vercode,HttpServletRequest request) throws IOException {
        String msg = null;
        Integer code = 0;
        Object data = null;
        try {
            // 登录,即身份验证
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            subject.login(token);
            // 在线用户维护
            //loginService.onlineUserList(getSession(), userId);
        }catch (UnknownAccountException e) {
            msg = "您输入的用户名不存在!";
            code = 1;
        }catch (IncorrectCredentialsException e) {
            msg = "您输入的密码有误!";
            code = 2 ;
        }catch (AuthenticationException e) {
            msg = "登陆异常,请重新登陆!";
            code = 3;
        }catch (RuntimeException e){
            msg = "账户被注销!";
            code = 4;
        }

两个过滤情形:

1)账户登录:
点击登录按钮,执行 subject.login(token);后会调用抽象类AuthenticatingRealm.getAuthenticationInfo方法,然后由实现类
UserRealm.doGetAuthenticationInfo方法执行验证密码。
2)未登录直接访问url:
对于请求地址符合authc过滤,过滤器会拦截url验证是否已经登录,执行AccessControlFilter的onPreHandle。先执行isAccessAllowed,若返回true,那么过滤器将直接放行,若返回false,执行或运算符后的onAccessDenied方法,那么再由其子类中的onAccessDenied方法处理后续逻辑。

关于shiro过滤器更详细的源码分析,请看
https://www.cnblogs.com/LeeScofiled/p/10511948.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值