Springmvc整合Apache Shiro 权限控制。

Springmvc整合Apache Shiro 权限控制。Apache Shiro 的是个优点:

(1)、使用简单、学习成本低。

(2)、体积轻量。

(3)、权限配置灵活,可以实现3层权限校验:无权限访问、用户级、方法级。


1、加载jar包。使用maven管理,添加pom.xml文件

        <shiro.version>1.2.4</shiro.version>     
        <!-- Shiro security -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-cas</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <!-- end of Shiro security -->

2、自定义方法,需要添加ShiroRealm.class,重写AuthenticationInfo(获取认证信息) ,AuthorizationInfo(获取授权信息)方法。

每个系统权限设计都不同,所有需要通过重写这两个方法,实现自己系统的获取认证信息、获取授权信息。

这里提供的是我本身系统的方法,仅仅提供思路,请自行修改。

package framework.common.shiro.shiro;

import org.springframework.beans.factory.annotation.Autowired;
import zteict.qinhuangdao.framework.base.utils.MD5;
import zteict.qinhuangdao.framework.common.shiro.service.ShiroService;
import org.apache.shiro.authc.*;
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 java.util.List;

/**
 * @author: football98
 * @createTime: 16-9-28
 * @classDescription:shiro 接口
 */
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    private ShiroService shiroService;

    /***
     * 获取认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken at) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) at;
        // 通过表单接收的用户名
        MD5 md5 = new MD5();
        String username = token.getUsername();
        String password = md5.getMD5ofStr(String.valueOf(token.getPassword()));

        if(!shiroService.findLoginname(username)){
            throw new UnknownAccountException(); //如果用户名错误
        }
        if (!shiroService.getUserByLoginname(username,password)) {
            throw new IncorrectCredentialsException(); //如果密码错误
        }
        return new SimpleAuthenticationInfo(username, token.getPassword(), getName());
    }
    /***
     * 获取授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
        // 根据自己系统规则的需要编写获取授权信息,这里为了快速入门只获取了用户对应角色的资源url信息
        String loginname = (String) pc.fromRealm(getName()).iterator().next();
        if (loginname != null) {
            List<String> pers = shiroService.getPermissionsByLoginname(loginname);
            if (pers != null && !pers.isEmpty()) {
                SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
                for (String each : pers) {
                    // 将权限资源添加到用户信息中
                    info.addStringPermission(each);
                }
                return info;
            }
        }
        return null;
    }
}

ShiroService

package framework.common.shiro.service;

import java.util.List;

/**
 * @author: football98
 * @createTime: 16-9-28
 * @classDescription:shiro service接口
 */
public interface ShiroService {
    /**
     * 判断用户名是否存在
     * @param loginname 登录名
     * @return 是/否
     */
    public boolean findLoginname(String loginname);
    /**
     * 判断登录名、密码是否正确
     * @param loginname 登录名
     * @param password 密码
     * @return 是/否
     */
    public boolean getUserByLoginname(String loginname,String password);
    /**
     * 获取用户权限列表
     * @param loginname 登录名
     * @return 用户权限列表
     */
    public List<String> getPermissionsByLoginname(String loginname);
}



ShiroServiceImpl

package framework.common.shiro.serviceImpl;

import zteict.qinhuangdao.framework.base.serviceImpl.BaseServiceImpl;
import zteict.qinhuangdao.framework.common.shiro.service.ShiroService;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import java.util.List;


/**
 * @author: football98
 * @createTime: 16-9-28
 * @classDescription:shiro service类
 */
@Service("shiroService")
public class ShiroServiceImpl extends BaseServiceImpl implements ShiroService {
    /**
     * 判断用户名是否存在
     * @param loginname 登录名
     * @return 是/否
     */
    public boolean findLoginname(String loginname){
        Session session = this.getSession();
        Query q = session.createQuery("select  count(tloginid) from Tlogin where loginname = :loginname ");
        q.setString("loginname",loginname);
        String count = q.uniqueResult()+"";
        if(count != null && count.equals("1")){
            return true;
        }else{
            return false;
        }
    }


    /**
     * 判断登录名、密码是否正确
     * @param loginname 登录名
     * @param password 密码
     * @return 是/否
     */
    public boolean getUserByLoginname(String loginname,String password){
        Session session = this.getSession();
        Query q = session.createQuery("select  count(tloginid) from Tlogin where loginname = :loginname and password = :password");
        q.setString("loginname",loginname);
        q.setString("password",password);
        String count = q.uniqueResult()+"";
        if(count != null && count.equals("1")){
            return true;
        }else{
            return false;
        }
    }
    /**
     * 获取用户权限列表
     * @param loginname 登录名
     * @return 用户权限列表
     */
    public List<String> getPermissionsByLoginname(String loginname) {
        //根据登录名获取用户角色id
        StringBuffer sql = new StringBuffer();
        sql.append(" select t.troleid ");
        sql.append("   from t_logintrole t ");
        sql.append("   left join t_login a on  t.tloginid = a.tloginid ");
        sql.append("  where a.loginname = :loginname ");
        String troleid = this.getSession().createSQLQuery(sql.toString()).setString("loginname",loginname).uniqueResult()+"";
        //根据角色id获取用户权限url
        StringBuffer sql2 = new StringBuffer();
        sql2.append(" select distinct t.url  ");
        sql2.append("   from t_permission t  ");
        sql2.append("  where t.tpermissionid in (select a.tpermissionid from t_roletpermission a where a.troleid = :troleid) ");
        List<String> list = this.getSession().createSQLQuery(sql2.toString()).setString("troleid",troleid).list();
        return list;
    }
}

3、xml配置

applicationContext-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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.0.xsd ">
    <!-- 缓存管理 -->
    <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" />

    <bean id="shiroRealm" class="framework.common.shiro.shiro.ShiroRealm"/>

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

    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"></property>
        <property name="loginUrl" value="/pages/login.jsp"></property>
        <property name="unauthorizedUrl" value="/"></property>
        <!-- 授权配置 -->
        <property name="filterChainDefinitions">
            <value>
                <!--与用户登录有关的权限 start-->
                /pages/login.jsp = anon
                /css/** = anon
                /images/** = anon
                /js/** = anon
                /stickyImg* = anon
                /loginUserController/login.do = anon
                <!--/roleController/save.do = authc , perms["roleController/save.do"] -->
                <!--角色模块授权 end-->
                /** = authc
            </value>
        </property>
    </bean>

</beans>

applicationContext-springmvc.xml

 <!-- 开启Shiro注解的Spring配置方式的beans。在lifecycleBeanPostProcessor之后运行 -->
    <aop:config proxy-target-class="true"/>
    <aop:aspectj-autoproxy proxy-target-class="true" />

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

4、方法级权限使用,用户登录方法

    /**
     * 用户登录
     * @param username 用户名
     * @param password 密码
     * @return 结果页面
     */
    @RequestMapping(value="login.do")
    @Log(name="用户登录")
    public String login(String username,String password,HttpServletRequest request) {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //token.setRememberMe(true);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            if (subject.isAuthenticated()) {
                LoginUserVO vo = loginUserService.loginUser(username);
                request.getSession().setAttribute("LOGINUSER", vo);
                //用户登录成功后,更新session Map,如重复登录,强制之前session过期
                String sessionid = SessionListener.userMap.get(username);
                if(sessionid != null&&!sessionid.equals("")){
                    //注销在线用户,如果session id 相同,不销毁。
                    if(!sessionid.equals(request.getSession().getId())){
                        SessionListener.sessionMap.get(sessionid).invalidate();
                        SessionListener.userMap.put(username,request.getSession().getId());
                        SessionListener.sessionMap.put(request.getSession().getId(),request.getSession());
                    }
                }else{
                    if(SessionListener.sessionMap.containsKey(request.getSession().getId())){
                        SessionListener.sessionMap.remove(request.getSession().getId());
                        for(String key : SessionListener.userMap.keySet()){
                            if(SessionListener.userMap.get(key).equals(request.getSession().getId())){
                                SessionListener.userMap.remove(key);
                            }
                        }
                    }
                    SessionListener.userMap.put(username,request.getSession().getId());
                    SessionListener.sessionMap.put(request.getSession().getId(),request.getSession());
                }
                return "index";
            }
        } catch (UnknownAccountException e) {
            request.setAttribute("ERROR", "用户名错误!");
        } catch (IncorrectCredentialsException e) {
            request.setAttribute("ERROR", "密码错误!");
        }
        return "login";
    }


在使用时,需要使用@RequiresPermissions()标签来完成。当然,spring必须开放    <context:annotation-config />配置

 /**
     * 查询角色信息
     * @param rolename 角色名
     * @param page 当前页
     * @param rows 每页显示多少条
     * @return 角色信息
     */
    @RequestMapping(value = "gridform1.do")
    @ResponseBody
    @RequiresPermissions("roleController/gridform1.do")
    public Object gridform1(String rolename, int page, int rows) {
        //总数
        int sum = roleService.queryCount(rolename);
        //分页信息
        Page p = new Page();
        p.setIntPage(page);
        p.setPageInfoCount(rows);
        //查询信息
        List<Trole> list = roleService.queryList(rolename, p) ;
        //返回结果
        Map<String, Object> result = new HashMap<String, Object>() ;
        result.put("total",sum);
        result.put("rows",list) ;
        return result;
    }





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值