1.application.ymlSpringCloud微服务之整合shiro

 2.pom.xml

SpringCloud微服务之整合shiro

3.编写自定义shiro realm

/**
 * FileName: MyShiroRealm
 * Date:     2018/12/5 15:07:07
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.XXXX.demo.shiro.config;

import com.XXXX.demo.api.vo.RoleVo;
import com.XXXX.demo.api.vo.UserVo;
import com.XXXX.demo.client.core.UserClientService;
import com.XXXX.demo.client.redis.RedisClient;
import com.XXXX.demo.common.pojo.resp.RespMsgBean;
import org.apache.shiro.SecurityUtils;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 〈一句话功能简述〉<br>
 * 自定义shiro realm
 * @create 2018/12/5 15:07:07
 * @since 1.0.0
 */
@Component
public class MyShiroRealm extends AuthorizingRealm {

    @Autowired
    private UserClientService userClientService;

    @Autowired
    private RedisClient redisClient;

    @Override
    public String getName() {
        return "MyShiroRealm";
    }

    /**
     * 身份认证
     * @prama
     * @return
     * @date 2018/12/5 15:40
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("————身份认证方法————");
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String name = token.getUsername();
        // 先从redis中获取用户信息,从数据库获取对应用户名密码的用户
        UserVo user = checkUserFromRedis(name);
        if (user.getPassword() == null || user == null) {
            throw new AccountException("用户名不正确!");
        } else if (!user.getPassword().equals(new String((char[]) token.getCredentials()))) {
            throw new AccountException("密码不正确!");
        }
        return new SimpleAuthenticationInfo(token.getPrincipal(), user.getPassword(), getName());
    }

    /**
     * 权限认证
     * @prama
     * @return
     * @date 2018/12/5 15:40
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//        //获取登录用户名
//        String name= (String) principalCollection.getPrimaryPrincipal();
//        //查询用户名称
//        RespMsgBean respMsgBean = userClientService.findByName(name);
//        UserVo user = (UserVo) respMsgBean.getData();
//        //添加角色和权限
//        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//        for (RoleVo role : user.getRoles()) {
//            //添加角色
//            simpleAuthorizationInfo.addRole(role.getRoleName());
//            for (PermissionVo permission:role.getPermissions()) {
//                //添加权限
//                simpleAuthorizationInfo.addStringPermission(permission.getPermissionName());
//            }
//        }
//        return simpleAuthorizationInfo;

        System.out.println("————权限认证————");
        String name = (String) SecurityUtils.getSubject().getPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获得该用户角色
        UserVo user = checkUserFromRedis(name);
        List<RoleVo> roles = user.getRoles();
        Set<String> set = new HashSet<>();
        //需要将 role 封装到 Set 作为 info.setRoles() 的参数
        roles.forEach((role)->{set.add(role.getRoleName());});
        //设置该用户拥有的角色
        info.setRoles(set);
        return info;

    }


    public UserVo checkUserFromRedis(String name){
        UserVo user = null;
        Map<String,UserVo> onLineMap = new HashMap<String, UserVo>();
        if(!redisClient.hasKeyOfMap("onLineMap",name)){
            RespMsgBean<UserVo> respMsgBean = userClientService.findByName(name);
            user = respMsgBean.getData();
            // 设置缓存
            redisClient.setOneMap("onLineMap",name,user,60*60*24*7);
//            redisClient.setValue(name,user,60*60*24*7);
        }else{
//            user = (UserVo) redisClient.getValue(name);
            user = (UserVo) redisClient.getValueOfMap("onLineMap",name);
        }
        return user;
    }

}
4.编写shiro配置类,注入相应的bean,此类上一定要加@Configuration注解

/**
 * FileName: ShiroConfig
 * Date:     2018/12/5 15:00:00
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.XXXX.demo.shiro.config;

import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 〈一句话功能简述〉<br>
 * shiro配置
 * @create 2018/12/5 15:00:00
 * @since 1.0.0
 */
@Configuration
public class ShiroConfig {

    /**
     * 将自己的验证方法注入容器
     * @prama
     * @return
     * @date 2018/12/5 15:28
     */
    @Bean
    public MyShiroRealm myShiroRealm() {
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        return myShiroRealm;
    }


    /**
     * 权限管理,配置主要的realm的管理认证
     * @prama
     * @return
     * @date 2018/12/5 15:30
     */
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 设置realm.
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    /**
     * Filter工厂,设置对应的过滤条件和跳转条件
     * @prama
     * @return
     * @date 2018/12/5 16:02
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // 必须设置 SecurityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 登录
        shiroFilterFactoryBean.setLoginUrl("/notLogin");
        // 设置无权限时跳转的 ur
        shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");
        // 设置拦截器
        Map<String,String> map = new LinkedHashMap<String, String>();
        // 普通用户
        map.put("/user/**", "roles[user]");
        // admin
        map.put("/admin/**", "roles[admin]");
        // 开放登陆接口
        map.put("/login", "anon");
        // 登出
//        map.put("/logout","logout");
        // 对所有用户认证
        map.put("/**","authc");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        System.out.println("Shiro拦截器工厂类注入成功");
        return shiroFilterFactoryBean;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}
5.编写相应的控制类请求

/**
 * FileName: LoginController
 * Date:     2018/12/6 15:15:15
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.XXXX.demo.shiro.rest;

import com.XXXX.demo.client.redis.RedisClient;
import com.XXXX.demo.common.pojo.resp.RespMsgBean;
import com.XXXX.demo.shiro.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * 〈一句话功能简述〉<br>
 * 测试shiro权限
 * @create 2018/12/6 15:15:15
 * @since 1.0.0
 */
@RestController
public class LoginController {

    @Resource
    private LoginService loginService;

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public RespMsgBean login(String name,String password){
        return new RespMsgBean().success(loginService.login(name,password));
    }

    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public RespMsgBean index(){
        return new RespMsgBean().success("登陆成功!");
    }

    @RequestMapping(value = "/notLogin", method = RequestMethod.GET)
    public RespMsgBean notLogin() {
        return new RespMsgBean().success("您尚未登陆!");
    }

    @RequestMapping(value = "/notRole", method = RequestMethod.GET)
    public RespMsgBean notRole() {
        return new RespMsgBean().success("您没有权限!");
    }

    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public RespMsgBean logout() {
        return new RespMsgBean().success(loginService.logout());
    }
}
 

分类:

技术点:

相关文章: