springboot+mybatis整合shiro核心类

springboot+mybatis整合shiro

1.什么是shiro?
Apache Shiro™ is a powerful and easy-to-use Java security framework that performs authentication, authorization, cryptography, and session management. With Shiro’s easy-to-understand API, you can quickly and easily secure any application – from the smallest mobile applications to the largest web and enterprise applications.

Apache Shiro™是一个功能强大且易于使用的Java安全框架,它执行身份验证,授权,加密和会话管理。使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移动应用程序到最大的Web和企业应用程序。
Shiro提供了用于执行以下方面的应用程序安全性API(我将其称为应用程序安全性的4个基石):

身份验证-证明用户身份,通常称为用户“登录”。
授权-访问控制
密码术-保护或隐藏数据以防窥视
会话管理-每个用户的时间敏感状态

2.使用shiro的三个核心组件是什么?
三个核心组件:Subject, SecurityManager 和 Realms.
Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。
  Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
  SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
  Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
  从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。
  Shiro内置了可以连接大量安全数据源(又名目录)的Realm,如LDAP、关系数据库(JDBC)、类似INI的文本配置资源以及属性文件等。如果缺省的Realm不能满足需求,你还可以插入代表自定义数据源的自己的Realm实现。

3.ShiroConfiguration类

package com.apache.shiroview.util;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;


@Configuration
public class ShiroConfiguration {

    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map filterChainDefinitionMap = new LinkedHashMap();
        shiroFilterFactoryBean.setLoginUrl("/showLogin");
        shiroFilterFactoryBean.setSuccessUrl("/index");
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        filterChainDefinitionMap.put("/login", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/userInfo/register", "anon"); // 注册表示可以匿名访问
        filterChainDefinitionMap.put("/userInfo/doLogin", "anon"); // 注册表示可以匿名访问
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/resources/static/css/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/fonts/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/css/**", "anon");//不需要验证
        filterChainDefinitionMap.put("/images/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/js/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/plugins/**", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/*", "authc");// 表示需要认证才可以访问
        filterChainDefinitionMap.put("/**", "authc");// 表示需要认证才可以访问
        filterChainDefinitionMap.put("/*.*", "authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;

    }
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); // 原来在这里
        return myShiroRealm;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    //散列算法
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName(PasswordHelper.ALGORITHM_NAME); // 散列算法
        hashedCredentialsMatcher.setHashIterations(PasswordHelper.HASH_ITERATIONS); // 散列次数
        return hashedCredentialsMatcher;
    }

    @Bean
    public PasswordHelper passwordHelper() {
        return new PasswordHelper();
    }
}

4.PasswordHelper

package com.apache.shiroview.util;

import com.apache.shiroview.domain.UserInfoModel;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;

public class PasswordHelper {
    private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
    public static final String ALGORITHM_NAME = "md5"; // 基础散列算法
    public static final int HASH_ITERATIONS = 2; // 自定义散列次数


    public void encryptPassword(UserInfoModel user){
        // 随机字符串作为salt因子,实际参与运算的salt我们还引入其它干扰因子
        user.setSalt(randomNumberGenerator.nextBytes().toHex());
        String newPassword = new SimpleHash(ALGORITHM_NAME, user.getPassword(),
                ByteSource.Util.bytes(user.getCredentialsSalt()), HASH_ITERATIONS).toHex();
        user.setPassword(newPassword);

    }

}

5.MyShiroRealm

/**
 * Copyright 2018 Goldwind Science & Technology.
 * All rights reserved. GOLDWIND PROPRIETARY/CONFIDENTIAL.
 * Use is subject to license terms.
 */
package com.apache.shiroview.util;

import com.apache.shiroview.domain.PermissionModel;
import com.apache.shiroview.domain.RoleModel;
import com.apache.shiroview.domain.UserInfoModel;
import com.apache.shiroview.domain.UserModel;
import com.apache.shiroview.service.UserInfoService;
import com.apache.shiroview.service.UserService;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collection;

/**
 * 身份校验核心类
 * 
 * @author Administrator
 *
 */

public class MyShiroRealm extends AuthorizingRealm {
    @Autowired
    private UserInfoService infoService ;

    /**
     * 认证信息(身份验证) Authentication 是用来验证用户身份
     * 
     * 输入 认证信息
     * 
     * 返回
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("身份认证-------------》doGetAuthenticationInfo");
        String username = (String) token.getPrincipal();
        UserInfoModel user = infoService.findUserByName(username);
        if (user == null) {
            return null;
        }
        // 获取用户的输入帐号
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUserName(), // 用户名
                user.getPassword(), ByteSource.Util.bytes(user.getCredentialsSalt()), getName());
        return authenticationInfo;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // TODO Auto-generated method stub
        System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");

        // 获取当前用户
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String username = (String) principals.getPrimaryPrincipal();
        UserInfoModel user = infoService.findUserByName(username);
        for (RoleModel role : user.getRoles()) {
            authorizationInfo.addRole(role.getRoleName());
            for (PermissionModel permission : role.getPermissList()) {
                authorizationInfo.addStringPermission(permission.getAuthName());
            }
        }
        return authorizationInfo;
    }

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

    private boolean hasAnyRoles(Collection<String> roleIdentifiers, AuthorizationInfo info) {
        if (roleIdentifiers != null && !roleIdentifiers.isEmpty()) {
            for (String roleName : roleIdentifiers) {
                if (hasRole(roleName, info)) {
                    return true;
                }
            }
            return false;
        }
        return true;
    }

}

6.UserInfoController

package com.apache.shiroview.controller;

import com.apache.shiroview.domain.UserInfoModel;
import com.apache.shiroview.service.UserInfoService;
import com.apache.shiroview.util.PasswordHelper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.*;

@Controller
@RequestMapping("/userInfo")
public class UserInfoController {
    @Autowired
    private PasswordHelper passwordHelper;
    @Autowired
    private UserInfoService userInfoService ;


    @RequestMapping("showLogin")
    public ModelAndView showLogin(){
         ModelAndView modelAndView = new ModelAndView("login");
        return modelAndView;
    }



    @GetMapping("doLogin")
    @ResponseBody
    public ModelAndView  doLogin(@RequestParam String username, @RequestParam String password) {
        ModelAndView modelAndView = new ModelAndView();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        //实现记住我
        token.setRememberMe(true);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
        } catch (IncorrectCredentialsException ice) {
            modelAndView.addObject("result", "密码错误");
            modelAndView.setViewName("login");
            return modelAndView;
        } catch (UnknownAccountException uae) {
            modelAndView.addObject("result", "用户不存在");
            modelAndView.setViewName("login");
            return modelAndView;
        }

        UserInfoModel user = userInfoService.findUserByName(username);
        subject.getSession().setAttribute("user", user);
        modelAndView.setViewName("index"); ;
        return modelAndView;
    }


    @GetMapping("register")
    @ResponseBody
    public Integer register(@RequestParam String username, @RequestParam String password) {
        UserInfoModel user = new UserInfoModel();
        user.setId(UUID.randomUUID().toString().replaceAll("-",""));
        user.setUserName(username);
        user.setPassword(password);
        int index = 0 ;
        passwordHelper.encryptPassword(user);
        try {
            userInfoService.saveUser(user);
            index = 1 ;
        } catch (Exception e) {
            e.printStackTrace();
            index = -1 ;
        }
        return index;
    }


}

你可能感兴趣的:(程序人生)