在SpringBoot中使用Shiro作权限验证

pom文件导入


        
            org.apache.shiro
            shiro-core
            1.4.0
        
        
            org.apache.shiro
            shiro-spring
            1.4.0
        
        
        
            org.apache.shiro
            shiro-ehcache
            1.4.0
        
        
            org.apache.shiro
            shiro-web
            1.4.0
        

Shiro权限配置主类


import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 描述:Shiro权限配置
 */
@Configuration
public class ShiroConfig {

    /**
     * ShiroFilterFactoryBean 处理拦截资源文件问题。
     * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在
     * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager
     *
     Filter Chain定义说明
     1、一个URL可以配置多个Filter,使用逗号分隔
     2、当设置多个过滤器时,全部验证通过,才视为通过
     3、部分过滤器可指定参数,如perms,roles
     *
     */
    @Bean
    public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager") SecurityManager manager){

        System.out.println("  。。。。shirFilter。。。。。。 ");

        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
        bean.setSecurityManager(manager);
        // 配置登录的url和登录成功的url

//        bean.setLoginUrl("/static/html/login.html");
//        bean.setSuccessUrl("/home");

        // 定义过滤器
        Map filterMap = new LinkedHashMap<>();
        filterMap.put("authc", new ShiroLoginFilter());
        filterMap.put("perms", new ShiroPermissionsFilter());
        bean.setFilters(filterMap);

        // 配置访问权限
        LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>();

        // 配置不同的URL采用的验证方式
        // anon表示可以匿名访问
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/info", "authc,perms");// 表示需要认证才可以访问
//        filterChainDefinitionMap.put("/**", "authc,perms");// 表示需要认证才可以访问
//        filterChainDefinitionMap.put("/*.*", "authc,perms");
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return bean;
    }

    // 配置核心安全事务管理器
    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier("userRealm") UserRealm userRealm) {
        System.err.println("--------------shiro已经加载----------------");
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(userRealm);
//        manager.setSessionManager(sessionManager);
//        manager.setCacheManager();
        return manager;
    }


    // 配置自定义的权限登录器
    @Bean(name = "userRealm")
    public UserRealm userRealm(@Qualifier("credentialsMatcher") CredentialsMatcher matcher) {
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(matcher);
        return userRealm;
    }

    // 配置自定义的密码匹配比较器
    @Bean(name = "credentialsMatcher")
    public CredentialsMatcher credentialsMatcher() {
        return new CredentialsMatcher();
    }
}

密码匹配

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;

/**
 * 
 * 描述:密码匹配比较
 */
public class CredentialsMatcher extends SimpleCredentialsMatcher {

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

        System.out.println("....密码的比对....");


        UsernamePasswordToken utoken = (UsernamePasswordToken) token;
        // 获得用户输入的密码:(可以采用加盐(salt)的方式去检验)
        String inPassword = new String(utoken.getPassword());
        // 获得数据库中的密码
        String dbPassword = (String) info.getCredentials();
        // 进行密码的比对
        return this.equals(inPassword, dbPassword);
    }

}

用户


/**
 * 描述:用户
 */
public class User {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

登录及授权

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.ArrayList;
import java.util.List;

/**
 *
 * 描述:登录及授权
 */
public class UserRealm extends AuthorizingRealm {

    // 认证.登录 提供账户信息返回认证信息
    /**
     * 当调用如下代码时会进入这个方法(一般是登录页面)
     * Subject currentUser = SecurityUtils.getSubject();
     * currentUser.login(token);
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {

        UsernamePasswordToken utoken = (UsernamePasswordToken) authenticationToken; // 获取用户输入的token
        System.out.println(".....认证.登录....");

        //根据用户名去数据库查询相关记录,并返回验证
        String username = utoken.getUsername();
        //
        User user = new User();
        user.setUsername(username);
        user.setPassword("123456");

        if (user == null) {
            return null;
        }
        return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());
    }

    // 授权 角色
//    提供用户信息返回权限信息
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        // 获取session中的用户
        User user = (User) principalCollection.fromRealm(this.getClass().getName()).iterator().next();

        System.out.println();
        System.out.println(".....授权....");
        System.out.println();

        List permissions = new ArrayList<>();
        permissions.add("abc1");
        permissions.add("abc2");
//        Set roles = user.getRoles();
//        for (Role role : roles) {
//            Set modules = role.getModules();
//            for (Module module : modules) {
//                permissions.add(module.getCode());
//            }
//        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissions); // 将权限放入shiro中.
        return info;
    }

}

判断是否已经登录


import org.apache.shiro.web.servlet.AdviceFilter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * 判断是否登录的过滤器,被Shiro组件调用使用
 */
public class ShiroLoginFilter  extends AdviceFilter {

    /**
     * 在访问controller前判断是否登录,返回json,不进行重定向。
     *
     * @param request
     * @param response
     * @return true-通过验证,false-验证失败
     * @throws Exception
     */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;

        User User = (User) httpServletRequest.getSession().getAttribute("user");

        httpServletRequest.getSession().setMaxInactiveInterval(36000);
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        httpServletResponse.setHeader("Access-Control-Allow-Headers", "x-requested-with");
        PrintWriter printWriter = null;
        if (null == User) {
            try {
                printWriter = response.getWriter();
                printWriter.write("{\"errorCode\": \"未登录\"}");
                printWriter.flush();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (printWriter != null) {
                    printWriter.close();
                }
            }
            return false;
        }
        return true;
    }
}

判断是否有权限


import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.springframework.beans.factory.annotation.Autowired;

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

/**
 *
 * 描述:验证是否有权限的过滤器
 */
public class ShiroPermissionsFilter extends PermissionsAuthorizationFilter {


    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {

        // 记录日志
        Subject subject = this.getSubject(request, response);

        /**获取用户信息,可以根据用户信息查看有没有对应模块的权限*/
        User user = (User) subject.getPrincipal();

        //true有权限; false没有权限
        boolean isPermitted = false;

        HttpServletRequest httpServletRequest = (HttpServletRequest) request;


        String code = httpServletRequest.getParameter("cmd");

        //写死一个权限作为测试
        if(code.equals("100"))//如何cmd=100就有权限
            isPermitted = true;

        return isPermitted;
    }

    /**
     * shiro认证perms资源失败后回调方法
     *
     * @param servletRequest
     * @param servletResponse
     * @return
     * @throws IOException
     */
    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws IOException {
        PrintWriter printWriter = null;
        try {
            servletResponse.setCharacterEncoding("UTF-8");
            servletResponse.setContentType("application/json");
            printWriter = servletResponse.getWriter();
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;


            printWriter.write("{\"error\": \"没有权限\"}");


            printWriter.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (printWriter != null) {
                printWriter.close();
            }
        }
        return false;
    }
}

Controller


import com.szcentral.conf.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by cgz on 2018-04-08 14:11
 * 描述:
 */
@RestController
public class SampleController {
    @RequestMapping("/")
    String home() {
        return "Hello World!";
    }

    @RequestMapping("/info")
    public Map getMap(){
        Map map = new HashMap();
        map.put("name", "chen");
        map.put("age", "22");
        map.put("tel", "13682452210");
        return map;
    }

    @RequestMapping("/login")
    public String login(HttpSession session,
                        HttpServletRequest request,
                        HttpServletResponse response){
        System.out.println("...接收登录Controller。。。。");
        //添加用户认证信息
        Subject subject = SecurityUtils.getSubject();
        String username = "chen";
        String pwd = "123456";
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, pwd);
        //进行验证,这里可以捕获异常,然后返回对应信息
        subject.login(usernamePasswordToken);


        User user = (User) subject.getPrincipal();
        session.setAttribute("user", user);

        return "login";
    }

}

你可能感兴趣的:(在SpringBoot中使用Shiro作权限验证)