Shiro-Spring 授权操作

Posted 998295czjzyt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Shiro-Spring 授权操作相关的知识,希望对你有一定的参考价值。

技术图片

  Subject进行Shiro的授权操作,首先委托给Security Manager,在由Security Manager 委托给Authenticator,由Authenticator授权器进行真正的授权操作。

  这里记录在Spring环境下配置Shiro框架。

  1、加入依赖:org.apache.shiro-core ,org.apache.shiro-web,org.apache.shiro-spring 版本都为1.2.2

  2、在web.xml中加入ShiroFilter代理类

    shiro和spring的集成需要代理类,这个shiro过滤器会从spring的容器中寻找真正的ShiroFilter

      注:filter-name必须和配置文件真实的Bean一致

<filter>
  <filter-name>shiroFilter</filter-name><!--shiroFilter必须和shiro配置文件(spring-shiro.xml)中真实的ShiroFilterBeanId一致-->
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  3、在IOC容器中配置真正的ShiroFilter,这里创建一个专门用于Shiro的配置文件

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="SecurityManager"/>
        <property name="loginUrl" value="/webroot/html/login.html"/>
        <property name="filterChainDefinitions">
            <value>
                /webroot/js/**=anon
                /wxbackstage/login=anon
                /**=authc
            </value>
        </property>

 

   在shiroFilter Bean的属性中,securityManager是必须的,这里依赖SecurityManager

   loginUrl,没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。

  successUrl :登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。

  unauthorizedUrl :没有权限默认跳转的页面

  filterChainDefinitions(重点):这是一个Shiro过滤链,配置哪些web的资源需要认证(Authentication)才能访问,哪些资源需要授权(Authorization)才能访问。

      格式:url=过滤器

      默认的过滤器:anon – org.apache.shiro.web.filter.authc.AnonymousFilter 
             authc – org.apache.shiro.web.filter.authc.FormAuthenticationFilter 
             authcBasic – org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter 
             perms – org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter 
             port – org.apache.shiro.web.filter.authz.PortFilter 
                rest – org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter 
             roles – org.apache.shiro.web.filter.authz.RolesAuthorizationFilter 
                ssl – org.apache.shiro.web.filter.authz.SslFilter 
             user – org.apache.shiro.web.filter.authc.UserFilter 
             logout – org.apache.shiro.web.filter.authc.LogoutFilter

     配置例子:

             /**=anon:所有的资源匿名也可以访问

            /admin/**=authc:admin下的所有网页或者请求方法都需要认证才能访问

 

            /admin/user=roles[admin]:admin/user下的网页或者请求方法需要有admin这个角色才能访问,参数是多个必须逗号分开,加上引号,如:rolse["admin1,admin2"]

            /**=rest[user]:分区请求方法,相当于/**=perms[user:method],其中,method代表,get,post,put,delete等等

            /**=port[8081],请求的url端口为8081,不是的话跳转到该端口进行url访问

            /admins/user/**=authcBasic:没有参数表示httpBasic认证

            /admins/user/**=ssl:没有参数,表示安全的url请求,协议为https

            /admins/user/**=user:没有参数表示必须存在用户,当登入操作时不做检查

 

     4、配置在Shiro配置文件中配置SecurityManager

 <bean id="SecurityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm"  ref="StudentRealm"></property>
        <!--配置多个realm 可增加数据安全性
         <property name="realms" >
            <list>
                <ref bean="Realm1"/>
                <ref bean="Realm2"/>
            </list>
        -->
    </bean>

 

        这个Security Manager依赖自定义的 realm,自定义Realm可以是一个,也可以是多个

     5、配置自定义realm

<bean id="StudentRealm" class="common.Shiro.StudentRealm">
        <property name="wxMemberDAO" ref="wxMemberDAOImpl"></property>
<!--加密器,不管--> <property name="credentialsMatcher" ref="credentialsMarcher"></property> </bean>

 

 自定义的realm来自SutdentRealm,同时注入了一个wxMemberDAO接口,并引入实例,从而访问数据库。(在wxMemberDAOImpl class中加入@Repository,从而获取该类bean实例)

  5、配置自定义realm

 

public class StudentRealm extends AuthorizingRealm {

    //注入DAO ,同时在spring-shiro的自定义Realm进行配置
    @Setter
    public WxMemberDAO wxMemberDAO;

    private Log log = LogFactory.getLog(StudentRealm.class);
    public String getName() {
        return "StudentRealm";
    }
   /* 
   * @Description: 授权器,验证角色身份权限的API 
   * @Param:  principalCollection
   * @return:  org.apache.shiro.authc.AuthenticationInfo
   * @Author:  zhijie
   * @Date: 2019/2/6 
   */ 
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }


  /* 
  * @Description:验证器,判断用户的登录  用户输入的账号密码封装成UserNamePasswordToken
  * SimpleAuthenticationInfo封装查询之后的结果
  * @Param: [authenticationToken] 
  * @return: org.apache.shiro.authc.AuthenticationInfo 
  * @Author:  zhijie
  * @Date: 2019/2/6
  */  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

      //通过 token获取用户名,查询数据库返回用户信息
      String memberId = (String) authenticationToken.getPrincipal();
      GroupMember groupMember = wxMemberDAO.login(memberId);
      if(groupMember == null) {
          log.info(memberId+"没找到帐号");
            throw new AuthenticationException();
      }

      SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(memberId,groupMember.getmemberpassword(), ByteSource.Util.bytes(memberId),getName());

        return simpleAuthenticationInfo;
    }
}

 

 

 

  继承AuthorizingRealm,更方便的继承认证和授权两个方法,先通过@Setter注入wxMemberDAO实例,在从第四步进行真正的注入。在重点看AuthenticationInfo的doGetAuthenticationInfo的方法。

    通过getPrincipal()获取username,在通过login方法获取member的对象,如果不存在,则抛出异常,否则返回一个SimpleAuthenticationInfo的对象。

      这个方法的参数:用户名,密码,盐(不管),这个realm的名字。

 

  6.从service中执行login方法。

 

 public ConcurrentSkipListMap login(String memberid,String password) {
        //创建当前访问路径的主体
        Subject subject = SecurityUtils.getSubject();
        //判断是否已经进行认证
        if(subject.isAuthenticated() == false) {
            //将用户名和密码封装成UserNamePasswordToken
            UsernamePasswordToken token = new UsernamePasswordToken(memberid,password);
            subject.login(token);
        }
        System.out.println(subject.isAuthenticated());
        GroupMember memberDepartmentPosition = wxMemberDAO.login(memberid);
        concurrentSkipListMap.put("AuthorizationStatus",memberDepartmentPosition.getDepartmentposition());

        return concurrentSkipListMap;
    }

 

 因为已经在配置文件中配置了Security Manager,所以这里直接获取访问主体即可。判断是否已经进行了认证,最终在result中返回json的格式。

  技术图片

 












以上是关于Shiro-Spring 授权操作的主要内容,如果未能解决你的问题,请参考以下文章

shiro安全框架-用户认证授权以及权限控制

SpringBoot技术专题「权限校验专区」Shiro整合JWT授权和认证实现

SpringBoot技术专题「实战开发系列」带你一同探索Shiro整合JWT授权和认证实战开发

VSCode自定义代码片段——git命令操作一个完整流程

SpringBoot集成Shiro

VSCode自定义代码片段15——git命令操作一个完整流程