[Shiro] - shiro之SSM中的使用

在学习shiro的途中,在github发现了一个开源项目,所需的控件刚好是自己要学习的方向.

虽然还要学习完ssm的shiro与springboot的shiro,以及接下来的种种控件和类库,但学习这个开源项目刻不容缓

 

[SSM的shiro使用]

SSM简单的说,就是SpringMVC负责web部分,mybatis负责数据库部分,否则没有mybatis要写的jdbc是很费时间的.

 

所以基于ssm的shiro项目,就是Servlet部分修改为SpringMVC,数据库部分,修改为Mybatis,然后把shiro集成进去,用这样一个思路来把项目实现.

老式Servlet:

package com.ykmimi.gobang.servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class LognServlet
 */
@WebServlet(description = "五子棋登陆", urlPatterns = { "/login" })
public class LoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");
        /* 获取用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        PrintWriter pw = response.getWriter();
        if(username.equals("admin") && password.equals("admin")) {
            pw.print("登陆成功!?");
            request.getRequestDispatcher("gobang.jsp");
        }else {
            pw.print("登陆失败,请核对账户及密码.?");
//            request.getRequestDispatcher("");
        }
        
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

而SpringMVC:

package com.ykmimi.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

import com.ykmimi.bean.User;

@Controller
public class UserController {

    @RequestMapping("login")
    public String login(User u,ModelMap map,HttpSession session) {
        System.out.println(u.getName()+":"+u.getPassword());
        /*map.put("uname", u.getName());
        map.put("upassword", u.getPassword());*/
        session.setAttribute("User", u);
        return "show";
    }
}

可以看出Servlet的方式是通过request,response配合doGet,doPost请求进行数据的传递,而

SpringMVC是通过将一整个数据封装为bean对象,继而返回页面或者返回@ResponseBody形式(JSON).

上面将整个User用户放入了session中,这个好像不是很提倡的做法,不过这里是做个测试.

再看一眼老式的JDBC:

package com.ykmimi.ipchecker.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import com.ykmimi.ipchecker.entity.SearchingData;
import com.ykmimi.ipchecker.util.JDBCUtil;

public class IPAddressDao {

    /* 插入新数据到表addressIp
    public void insertSomeData(SearchingData sdata) throws SQLException, ClassNotFoundException {
        Connection conn = null;
        PreparedStatement ps = null;
        String sql = "insert into addressIp values(nextval('seq_addressIp'),?,?,current_date)";
        try {
        conn= JDBCUtil.getConnection();
        ps = conn.prepareStatement(sql);
        ps.setString(1, sdata.getIpDomain());
        ps.setString(2, sdata.getIp());
        ps.executeUpdate();
        }finally {
            JDBCUtil.close(null, ps, null);
        }
        
    }
}

当使用之前老式的JDBC时,要分别对insert,select,update,delete等操作进行区分,牵扯到的有将不同的语句执行不同的方法.

比如select查询要执行executeQuery(),而其它的执行上面代码中的executeUpdate(),以及每个SQL语句都将写在java类中,

这与"高内聚,低耦合"的Java信条不符合,(比如SQL要进行更改时),那么就是要将SQL语句进行在解耦,Mybatis框架实现了这一操作.

Mybatis可以参考之前ukzq自己写的两篇博客 Mybatis体系结构 Mybatis基本工作原理

 

[代码分析]

how2j的作者偶尔也会犯错,但ssm的shiro运行还是可以的,依旧是几个页面的测试.

这里主要看一下realm包下的DatabaseRealm这个类:

package com.how2java.realm;

import java.util.Set;

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.authc.UsernamePasswordToken;
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.springframework.beans.factory.annotation.Autowired;

import com.how2java.service.PermissionService;
import com.how2java.service.RoleService;
import com.how2java.service.UserService;

public class DatabaseRealm extends AuthorizingRealm {

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;
    
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //能进入到这里,表示账号已经通过验证了
        String userName =(String) principalCollection.getPrimaryPrincipal();
        //通过service获取角色和权限
        Set<String> permissions = permissionService.listPermissions(userName);
        Set<String> roles = roleService.listRoles(userName);
        
        //授权对象
        SimpleAuthorizationInfo s = new SimpleAuthorizationInfo();
        //把通过service获取到的角色和权限放进去
        s.setStringPermissions(permissions);
        s.setRoles(roles);
        return s;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取账号密码
        UsernamePasswordToken t = (UsernamePasswordToken) token;
        String userName= token.getPrincipal().toString();
        String password= new String( t.getPassword());
        //获取数据库中的密码
        String passwordInDB = userService.getPassword(userName);

        
        //如果为空就是账号不存在,如果不相同就是密码错误,但是都抛出AuthenticationException,而不是抛出具体错误原因,免得给破解者提供帮助信息
        if(null==passwordInDB || !passwordInDB.equals(password)) 
            throw new AuthenticationException();
        
        //认证信息里存放账号密码, getName() 是当前Realm的继承方法,通常返回当前类名 :databaseRealm
        SimpleAuthenticationInfo a = new SimpleAuthenticationInfo(userName,password,getName());
        return a;
    }

}

这个类继承了AuthorizingRealm,这个授权Realm,这个Realm就像how2j站长说的那样确实取的名字不够贴切,比较难以理解,说白了可能就是个用来获取用户,对比用户名以及查看其权限的一个领域.

(我更喜欢把这个Realm想象为一个大多数小区和学校,公司门口的那种栅栏,检验关口,那个地方就统称为一个域,Realm吧)

查看被继承的AuthorizingRealm,其内容大概看英文就理解为其内部实现的是一切查看验证权限,角色相关的操作,

抽空应该查看一下Shiro确切的代码解析博客.

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.shiro.realm;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Authorizer;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.authz.permission.PermissionResolver;
import org.apache.shiro.authz.permission.PermissionResolverAware;
import org.apache.shiro.authz.permission.RolePermissionResolver;
import org.apache.shiro.authz.permission.RolePermissionResolverAware;
import org.apache.shiro.authz.permission.WildcardPermissionResolver;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.util.Initializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AuthorizingRealm extends AuthenticatingRealm implements Authorizer, Initializable, PermissionResolverAware, RolePermissionResolverAware {
    private static final Logger log = LoggerFactory.getLogger(AuthorizingRealm.class);
    private static final String DEFAULT_AUTHORIZATION_CACHE_SUFFIX = ".authorizationCache";
    private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
    private boolean authorizationCachingEnabled;
    private Cache<Object, AuthorizationInfo> authorizationCache;
    private String authorizationCacheName;
    private PermissionResolver permissionResolver;
    private RolePermissionResolver permissionRoleResolver;

    public AuthorizingRealm() {
        this((CacheManager)null, (CredentialsMatcher)null);
    }

    public AuthorizingRealm(CacheManager cacheManager) {
        this(cacheManager, (CredentialsMatcher)null);
    }

    public AuthorizingRealm(CredentialsMatcher matcher) {
        this((CacheManager)null, matcher);
    }

    public AuthorizingRealm(CacheManager cacheManager, CredentialsMatcher matcher) {
        if (cacheManager != null) {
            this.setCacheManager(cacheManager);
        }

        if (matcher != null) {
            this.setCredentialsMatcher(matcher);
        }

        this.authorizationCachingEnabled = true;
        this.permissionResolver = new WildcardPermissionResolver();
        int instanceNumber = INSTANCE_COUNT.getAndIncrement();
        this.authorizationCacheName = this.getClass().getName() + ".authorizationCache";
        if (instanceNumber > 0) {
            this.authorizationCacheName = this.authorizationCacheName + "." + instanceNumber;
        }

    }

    public void setName(String name) {
        super.setName(name);
        String authzCacheName = this.authorizationCacheName;
        if (authzCacheName != null && authzCacheName.startsWith(this.getClass().getName())) {
            this.authorizationCacheName = name + ".authorizationCache";
        }

    }

    public void setAuthorizationCache(Cache<Object, AuthorizationInfo> authorizationCache) {
        this.authorizationCache = authorizationCache;
    }

    public Cache<Object, AuthorizationInfo> getAuthorizationCache() {
        return this.authorizationCache;
    }

    public String getAuthorizationCacheName() {
        return this.authorizationCacheName;
    }

    public void setAuthorizationCacheName(String authorizationCacheName) {
        this.authorizationCacheName = authorizationCacheName;
    }

    public boolean isAuthorizationCachingEnabled() {
        return this.isCachingEnabled() && this.authorizationCachingEnabled;
    }

    public void setAuthorizationCachingEnabled(boolean authenticationCachingEnabled) {
        this.authorizationCachingEnabled = authenticationCachingEnabled;
        if (authenticationCachingEnabled) {
            this.setCachingEnabled(true);
        }

    }

    public PermissionResolver getPermissionResolver() {
        return this.permissionResolver;
    }

    public void setPermissionResolver(PermissionResolver permissionResolver) {
        if (permissionResolver == null) {
            throw new IllegalArgumentException("Null PermissionResolver is not allowed");
        } else {
            this.permissionResolver = permissionResolver;
        }
    }

    public RolePermissionResolver getRolePermissionResolver() {
        return this.permissionRoleResolver;
    }

    public void setRolePermissionResolver(RolePermissionResolver permissionRoleResolver) {
        this.permissionRoleResolver = permissionRoleResolver;
    }

    protected void onInit() {
        super.onInit();
        this.getAvailableAuthorizationCache();
    }

    protected void afterCacheManagerSet() {
        super.afterCacheManagerSet();
        this.getAvailableAuthorizationCache();
    }

    private Cache<Object, AuthorizationInfo> getAuthorizationCacheLazy() {
        if (this.authorizationCache == null) {
            if (log.isDebugEnabled()) {
                log.debug("No authorizationCache instance set.  Checking for a cacheManager...");
            }

            CacheManager cacheManager = this.getCacheManager();
            if (cacheManager != null) {
                String cacheName = this.getAuthorizationCacheName();
                if (log.isDebugEnabled()) {
                    log.debug("CacheManager [" + cacheManager + "] has been configured.  Building authorization cache named [" + cacheName + "]");
                }

                this.authorizationCache = cacheManager.getCache(cacheName);
            } else if (log.isDebugEnabled()) {
                log.debug("No cache or cacheManager properties have been set.  Authorization cache cannot be obtained.");
            }
        }

        return this.authorizationCache;
    }

    private Cache<Object, AuthorizationInfo> getAvailableAuthorizationCache() {
        Cache<Object, AuthorizationInfo> cache = this.getAuthorizationCache();
        if (cache == null && this.isAuthorizationCachingEnabled()) {
            cache = this.getAuthorizationCacheLazy();
        }

        return cache;
    }

    protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            return null;
        } else {
            AuthorizationInfo info = null;
            if (log.isTraceEnabled()) {
                log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
            }

            Cache<Object, AuthorizationInfo> cache = this.getAvailableAuthorizationCache();
            Object key;
            if (cache != null) {
                if (log.isTraceEnabled()) {
                    log.trace("Attempting to retrieve the AuthorizationInfo from cache.");
                }

                key = this.getAuthorizationCacheKey(principals);
                info = (AuthorizationInfo)cache.get(key);
                if (log.isTraceEnabled()) {
                    if (info == null) {
                        log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
                    } else {
                        log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
                    }
                }
            }

            if (info == null) {
                info = this.doGetAuthorizationInfo(principals);
                if (info != null && cache != null) {
                    if (log.isTraceEnabled()) {
                        log.trace("Caching authorization info for principals: [" + principals + "].");
                    }

                    key = this.getAuthorizationCacheKey(principals);
                    cache.put(key, info);
                }
            }

            return info;
        }
    }

    protected Object getAuthorizationCacheKey(PrincipalCollection principals) {
        return principals;
    }

    protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        if (principals != null) {
            Cache<Object, AuthorizationInfo> cache = this.getAvailableAuthorizationCache();
            if (cache != null) {
                Object key = this.getAuthorizationCacheKey(principals);
                cache.remove(key);
            }

        }
    }

    protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection var1);

    protected Collection<Permission> getPermissions(AuthorizationInfo info) {
        Set<Permission> permissions = new HashSet();
        if (info != null) {
            Collection<Permission> perms = info.getObjectPermissions();
            if (!CollectionUtils.isEmpty(perms)) {
                permissions.addAll(perms);
            }

            perms = this.resolvePermissions(info.getStringPermissions());
            if (!CollectionUtils.isEmpty(perms)) {
                permissions.addAll(perms);
            }

            perms = this.resolveRolePermissions(info.getRoles());
            if (!CollectionUtils.isEmpty(perms)) {
                permissions.addAll(perms);
            }
        }

        return permissions.isEmpty() ? Collections.emptySet() : Collections.unmodifiableSet(permissions);
    }

    private Collection<Permission> resolvePermissions(Collection<String> stringPerms) {
        Collection<Permission> perms = Collections.emptySet();
        PermissionResolver resolver = this.getPermissionResolver();
        if (resolver != null && !CollectionUtils.isEmpty(stringPerms)) {
            perms = new LinkedHashSet(stringPerms.size());
            Iterator var4 = stringPerms.iterator();

            while(var4.hasNext()) {
                String strPermission = (String)var4.next();
                Permission permission = this.getPermissionResolver().resolvePermission(strPermission);
                ((Collection)perms).add(permission);
            }
        }

        return (Collection)perms;
    }

    private Collection<Permission> resolveRolePermissions(Collection<String> roleNames) {
        Collection<Permission> perms = Collections.emptySet();
        RolePermissionResolver resolver = this.getRolePermissionResolver();
        if (resolver != null && !CollectionUtils.isEmpty(roleNames)) {
            perms = new LinkedHashSet(roleNames.size());
            Iterator var4 = roleNames.iterator();

            while(var4.hasNext()) {
                String roleName = (String)var4.next();
                Collection<Permission> resolved = resolver.resolvePermissionsInRole(roleName);
                if (!CollectionUtils.isEmpty(resolved)) {
                    ((Collection)perms).addAll(resolved);
                }
            }
        }

        return (Collection)perms;
    }

    public boolean isPermitted(PrincipalCollection principals, String permission) {
        Permission p = this.getPermissionResolver().resolvePermission(permission);
        return this.isPermitted(principals, p);
    }

    public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        AuthorizationInfo info = this.getAuthorizationInfo(principals);
        return this.isPermitted(permission, info);
    }

    protected boolean isPermitted(Permission permission, AuthorizationInfo info) {
        Collection<Permission> perms = this.getPermissions(info);
        if (perms != null && !perms.isEmpty()) {
            Iterator var4 = perms.iterator();

            while(var4.hasNext()) {
                Permission perm = (Permission)var4.next();
                if (perm.implies(permission)) {
                    return true;
                }
            }
        }

        return false;
    }

    public boolean[] isPermitted(PrincipalCollection subjectIdentifier, String... permissions) {
        List<Permission> perms = new ArrayList(permissions.length);
        String[] var4 = permissions;
        int var5 = permissions.length;

        for(int var6 = 0; var6 < var5; ++var6) {
            String permString = var4[var6];
            perms.add(this.getPermissionResolver().resolvePermission(permString));
        }

        return this.isPermitted((PrincipalCollection)subjectIdentifier, (List)perms);
    }

    public boolean[] isPermitted(PrincipalCollection principals, List<Permission> permissions) {
        AuthorizationInfo info = this.getAuthorizationInfo(principals);
        return this.isPermitted(permissions, info);
    }

    protected boolean[] isPermitted(List<Permission> permissions, AuthorizationInfo info) {
        boolean[] result;
        if (permissions != null && !permissions.isEmpty()) {
            int size = permissions.size();
            result = new boolean[size];
            int i = 0;

            Permission p;
            for(Iterator var6 = permissions.iterator(); var6.hasNext(); result[i++] = this.isPermitted(p, info)) {
                p = (Permission)var6.next();
            }
        } else {
            result = new boolean[0];
        }

        return result;
    }

    public boolean isPermittedAll(PrincipalCollection subjectIdentifier, String... permissions) {
        if (permissions != null && permissions.length > 0) {
            Collection<Permission> perms = new ArrayList(permissions.length);
            String[] var4 = permissions;
            int var5 = permissions.length;

            for(int var6 = 0; var6 < var5; ++var6) {
                String permString = var4[var6];
                perms.add(this.getPermissionResolver().resolvePermission(permString));
            }

            return this.isPermittedAll((PrincipalCollection)subjectIdentifier, (Collection)perms);
        } else {
            return false;
        }
    }

    public boolean isPermittedAll(PrincipalCollection principal, Collection<Permission> permissions) {
        AuthorizationInfo info = this.getAuthorizationInfo(principal);
        return info != null && this.isPermittedAll(permissions, info);
    }

    protected boolean isPermittedAll(Collection<Permission> permissions, AuthorizationInfo info) {
        if (permissions != null && !permissions.isEmpty()) {
            Iterator var3 = permissions.iterator();

            while(var3.hasNext()) {
                Permission p = (Permission)var3.next();
                if (!this.isPermitted(p, info)) {
                    return false;
                }
            }
        }

        return true;
    }

    public void checkPermission(PrincipalCollection subjectIdentifier, String permission) throws AuthorizationException {
        Permission p = this.getPermissionResolver().resolvePermission(permission);
        this.checkPermission(subjectIdentifier, p);
    }

    public void checkPermission(PrincipalCollection principal, Permission permission) throws AuthorizationException {
        AuthorizationInfo info = this.getAuthorizationInfo(principal);
        this.checkPermission(permission, info);
    }

    protected void checkPermission(Permission permission, AuthorizationInfo info) {
        if (!this.isPermitted(permission, info)) {
            String msg = "User is not permitted [" + permission + "]";
            throw new UnauthorizedException(msg);
        }
    }

    public void checkPermissions(PrincipalCollection subjectIdentifier, String... permissions) throws AuthorizationException {
        if (permissions != null) {
            String[] var3 = permissions;
            int var4 = permissions.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                String permString = var3[var5];
                this.checkPermission(subjectIdentifier, permString);
            }
        }

    }

    public void checkPermissions(PrincipalCollection principal, Collection<Permission> permissions) throws AuthorizationException {
        AuthorizationInfo info = this.getAuthorizationInfo(principal);
        this.checkPermissions(permissions, info);
    }

    protected void checkPermissions(Collection<Permission> permissions, AuthorizationInfo info) {
        if (permissions != null && !permissions.isEmpty()) {
            Iterator var3 = permissions.iterator();

            while(var3.hasNext()) {
                Permission p = (Permission)var3.next();
                this.checkPermission(p, info);
            }
        }

    }

    public boolean hasRole(PrincipalCollection principal, String roleIdentifier) {
        AuthorizationInfo info = this.getAuthorizationInfo(principal);
        return this.hasRole(roleIdentifier, info);
    }

    protected boolean hasRole(String roleIdentifier, AuthorizationInfo info) {
        return info != null && info.getRoles() != null && info.getRoles().contains(roleIdentifier);
    }

    public boolean[] hasRoles(PrincipalCollection principal, List<String> roleIdentifiers) {
        AuthorizationInfo info = this.getAuthorizationInfo(principal);
        boolean[] result = new boolean[roleIdentifiers != null ? roleIdentifiers.size() : 0];
        if (info != null) {
            result = this.hasRoles(roleIdentifiers, info);
        }

        return result;
    }

    protected boolean[] hasRoles(List<String> roleIdentifiers, AuthorizationInfo info) {
        boolean[] result;
        if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
            int size = roleIdentifiers.size();
            result = new boolean[size];
            int i = 0;

            String roleName;
            for(Iterator var6 = roleIdentifiers.iterator(); var6.hasNext(); result[i++] = this.hasRole(roleName, info)) {
                roleName = (String)var6.next();
            }
        } else {
            result = new boolean[0];
        }

        return result;
    }

    public boolean hasAllRoles(PrincipalCollection principal, Collection<String> roleIdentifiers) {
        AuthorizationInfo info = this.getAuthorizationInfo(principal);
        return info != null && this.hasAllRoles(roleIdentifiers, info);
    }

    private boolean hasAllRoles(Collection<String> roleIdentifiers, AuthorizationInfo info) {
        if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
            Iterator var3 = roleIdentifiers.iterator();

            while(var3.hasNext()) {
                String roleName = (String)var3.next();
                if (!this.hasRole(roleName, info)) {
                    return false;
                }
            }
        }

        return true;
    }

    public void checkRole(PrincipalCollection principal, String role) throws AuthorizationException {
        AuthorizationInfo info = this.getAuthorizationInfo(principal);
        this.checkRole(role, info);
    }

    protected void checkRole(String role, AuthorizationInfo info) {
        if (!this.hasRole(role, info)) {
            String msg = "User does not have role [" + role + "]";
            throw new UnauthorizedException(msg);
        }
    }

    public void checkRoles(PrincipalCollection principal, Collection<String> roles) throws AuthorizationException {
        AuthorizationInfo info = this.getAuthorizationInfo(principal);
        this.checkRoles(roles, info);
    }

    public void checkRoles(PrincipalCollection principal, String... roles) throws AuthorizationException {
        this.checkRoles((PrincipalCollection)principal, (Collection)Arrays.asList(roles));
    }

    protected void checkRoles(Collection<String> roles, AuthorizationInfo info) {
        if (roles != null && !roles.isEmpty()) {
            Iterator var3 = roles.iterator();

            while(var3.hasNext()) {
                String roleName = (String)var3.next();
                this.checkRole(roleName, info);
            }
        }

    }

    protected void doClearCache(PrincipalCollection principals) {
        super.doClearCache(principals);
        this.clearCachedAuthorizationInfo(principals);
    }
}

在DatabaseRealm中:

    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermissionService permissionService;

分别表示的是用户的service, 角色的service, 权限许可操作的service,用来执行不同的操作.

与SpringBoot不同的是SSM配置xml文件:

applicationContext-shiro.xml   把原来的shiro.ini进行了另一种写法的展示

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util.xsd">
    
    
    <!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 调用我们配置的权限管理器 -->
        <property name="securityManager" ref="securityManager" />
        <!-- 配置我们的登录请求地址 -->
        <property name="loginUrl" value="/login" />
        <!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
        <property name="unauthorizedUrl" value="/unauthorized" />
        <!-- 退出 -->
        <property name="filters">
            <util:map>
                <entry key="logout" value-ref="logoutFilter" />
            </util:map>
        </property>
        <!-- 权限配置 -->
        <property name="filterChainDefinitions">
            <value>
                <!-- anon表示此地址不需要任何权限即可访问 -->
                /login=anon
                /index=anon
                /static/**=anon
                /doLogout=logout
                <!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login -->
                /** = authc
            </value>
        </property>
    </bean>
    <!-- 退出过滤器 -->
    <bean id="logoutFilter" class="org.apache.shiro.web.filter.authc.LogoutFilter">
        <property name="redirectUrl" value="/index" />
    </bean>

    <!-- 会话ID生成器 -->
    <bean id="sessionIdGenerator"
        class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" />
    <!-- 会话Cookie模板 关闭浏览器立即失效 -->
    <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg value="sid" />
        <property name="httpOnly" value="true" />
        <property name="maxAge" value="-1" />
    </bean>
    <!-- 会话DAO -->
    <bean id="sessionDAO"
        class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO">
        <property name="sessionIdGenerator" ref="sessionIdGenerator" />
    </bean>
    <!-- 会话验证调度器,每30分钟执行一次验证 ,设定会话超时及保存 -->
    <bean name="sessionValidationScheduler"
        class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler">
        <property name="interval" value="1800000" />
        <property name="sessionManager" ref="sessionManager" />
    </bean>
    <!-- 会话管理器 -->
    <bean id="sessionManager"
        class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!-- 全局会话超时时间(单位毫秒),默认30分钟 -->
        <property name="globalSessionTimeout" value="1800000" />
        <property name="deleteInvalidSessions" value="true" />
        <property name="sessionValidationSchedulerEnabled" value="true" />
        <property name="sessionValidationScheduler" ref="sessionValidationScheduler" />
        <property name="sessionDAO" ref="sessionDAO" />
        <property name="sessionIdCookieEnabled" value="true" />
        <property name="sessionIdCookie" ref="sessionIdCookie" />
    </bean>

    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="databaseRealm" />
        <property name="sessionManager" ref="sessionManager" />
    </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="databaseRealm" class="com.how2java.realm.DatabaseRealm">
    </bean>
    
    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
</beans> 

applicationContext.xml  数据库连接,扫描mybatis的mapper什么的.

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
     http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
     http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
    
    

   <context:annotation-config />
    <context:component-scan base-package="com.how2java.service" />

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
      <property name="driverClassName">  
          <value>com.mysql.jdbc.Driver</value>  
      </property>  
      <property name="url">  
          <value>jdbc:mysql://localhost:3306/shiro?characterEncoding=UTF-8</value>  
    
      </property>  
      <property name="username">  
          <value>root</value>  
      </property>  
      <property name="password">  
          <value>yourpassword</value>
      </property>      
    </bean>
    
    
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="typeAliasesPackage" value="com.how2java.pojo" />
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:com/how2java/mapper/*.xml"/>
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.how2java.mapper"/>
    </bean>
    


</beans>

为什么zhang3只能点击进入删除订单的权限,而li4不能.?

deleteOrder.jsp ,能进来,就表示有deleteOrder权限 
返回

除了这两个xml,还有web.xml,springMVC.xml,并没有很显著地对点击路径进行Filter拦截,那样的话,如果项目比较大,拦截的页面会有很多

而且要根据不同角色,不同权限进行拦截,想起来都觉得麻烦.

这里看到PageController中,其实是使用了一个注解

package com.how2java.controller;


import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

//专门用于显示页面的控制器
@Controller
@RequestMapping("")
public class PageController {
    
    @RequestMapping("index")
    public String index(){
        return "index";
    }
    
    @RequiresPermissions("deleteOrder")
    @RequestMapping("deleteOrder")
    public String deleteOrder(){
        return "deleteOrder";
    }
    @RequiresRoles("productManager")
    @RequestMapping("deleteProduct")
    public String deleteProduct(){
        return "deleteProduct";
    }
    @RequestMapping("listProduct")
    public String listProduct(){
        return "listProduct";
    }
    
    @RequestMapping(value="/login",method=RequestMethod.GET)  
    public String login(){
        return "login";
    }
    @RequestMapping("unauthorized")
    public String noPerms(){
        return "unauthorized";
    }



}

除了熟悉的RequestMapping,Controller, 这里多出来两个,一个叫@RequiresPermissions("deleteOrder"),字面意思理解就是要访问这个deleteOrder路径的需要一个叫deleteOrder的权限

再返回去看数据库表中permission这个表的内容:

以及role_permission

看了这两个表就应该清楚的知道,一个表定义了整个shiro加入的系统中有哪些操作.

最后,role的id, 1,2,3, 对应 role_permission表中那些操作,比如role中id为1的admin,它具有permission表中1,2,3,4,5,6,7,8,9,10的操作.

如果一个方法同时声明多个这样的注解,那么它们的判定顺序跟注解的上下顺序无关,而是根据这个:

                                                        图片引自博客 某csdn

 

 依次看这些注解的含义:

 RequiresRoles -- 当前Subject必须拥有所指定的角色时,才能访问被该注解标注的方法,如果当Subject不同时,不拥有所有指定角色,则

方法不会执行,还会抛出AuthorizationException异常.

 RequiresPermissions -- 当前Subject需要拥有某些特定的权限时,才能执行被该注解标注的方法,就像上面的需要deleteOrder的权限,如

果当前Subject不具有这样的权限,则方法不会被执行.

 RequiresAuthentication -- 使用该注解标注的类,实例,方法在访问或调用时,当前Subject必须在当前session中已经过认证.

验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时。

 RequiresUser -- 当前Subject必须是应用的用户,才能访问或调用被该注解标注的类,实例,方法.

验证用户是否被记忆,user有两种含义:

一种是成功登录的(subject.isAuthenticated() 结果为true);

另外一种是被记忆的(subject.isRemembered()结果为true).

 RequiresGuest -- 使用该注解标注的类,实例,方法在访问或调用时,当前Subject可以是"guest"身份,不需要经过认证或在之前的session中存在记录.

验证是否是一个guest的请求,与@RequiresUser完全相反。换言之,RequiresUser  == !RequiresGuest。此时subject.getPrincipal() 结果为null.

 

 上面的web.xml中配置的filter是跟shiro相关的.

 <!-- Shiro配置 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <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>

springMVC.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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">



    <context:annotation-config/>

    <context:component-scan base-package="com.how2java.controller">
          <context:include-filter type="annotation" 
          expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <mvc:annotation-driven />
    
    <mvc:default-servlet-handler />


    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <!--启用shiro注解 -->
    <bean
        class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
        depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true" />
    </bean>
    <bean
        class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager" />
    </bean>
    
    <!-- 控制器异常处理 -->
    <bean id="exceptionHandlerExceptionResolver" class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
    </bean>
    <bean class="com.how2java.exception.DefaultExceptionHandler"/>    

</beans>

刚看了看B站上面的shiro教程,讲得好细. 放在之后听.

SSM的shiro到这里其实也没什么可记录的了,注意AuthorizationInfo这个对象可以存放角色和权限信息.

其它的根据权限5表设计的bean,对应的Mapper注意角色和权限是List集合,因为一个用户可能具备多种角色,多种权限.

这里接触到一个新的注解 @ResponseStatus

以及 @ExceptionHandler

以及 @ControllerAdvice 

 

 

今天ssm的shiro整理到这里,也基本差不多了.

转载于:https://www.cnblogs.com/ukzq/p/10227726.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值