Sprinboot mybatis整合shiro 登录,权限管理

首先感谢慕课网的老师,让我受益匪浅

https://www.imooc.com/video/16961

 

整体源码

 github地址:https://github.com/binlian/binglian-shiroLoginResit

实现了登录才可以访问其他网站,

实现了管理员的权限以及用户的权限,

我先总结一下所学的

我这里借用一下老师的图片

上面的C/C++、PHP这些都其实是主体subject 传过来

然后传给security Manager 在manager中又有认证,授权,会话这些

我们先看认证 subject 传给authenticator 然后传给Realms 而Realms 去调用数据库或者文本里面的数据进行验证()

授权一样,也是anthorizer 然后调用Realms 然后在掉数据库或文本

视频也详细介绍了 我会贴在整体架构里的最下面

shiro认证

 

shiro授权

 

然后我们再说下三个Realm

iniRealm 是文档 他获取文本里面的数据进行认证授权,

JDBCRealm 是从数据库中获取

自定义可以模拟数据库,也可以从数据库 自定义

我学习的github地址:https://github.com/binlian/shiro

 

 

首先我们看下目录

config就是配置shiro

controller 不多说 控制层

mapper和pojo是dao层和实体类 因为我这里使用的mybatis逆向工程

serviceImpl这里面是接口实现层 我Realm自定就放在这下面

数据库的创建

create table user(
	id int(32) not null auto_increment,
	username varchar(32) not null ,
	password varchar(32) not null,
	rolse enum('admin','user') not null default 'user',
	primary key(id)
)

然后我们先看下Dao和xml

这userMapper 继承工具类

这里声明接口在xml实现,为了让Realm获取 password和rolse进行认证和授权

package com.binglian.mapper;

import com.binglian.pojo.User;
import com.binglian.utils.MyMapper;

public interface UserMapper extends MyMapper<User> {
	
	//根据username返回password
	String getUserPassword(String username);
	
	//根据username返回rolse
	String getUserRolse(String username);
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.binglian.mapper.UserMapper" >
  <resultMap id="BaseResultMap" type="com.binglian.pojo.User" >
    <!--
      WARNING - @mbg.generated
    -->
    <id column="id" property="id" jdbcType="INTEGER" />
    <result column="username" property="username" jdbcType="VARCHAR" />
    <result column="password" property="password" jdbcType="VARCHAR" />
    <result column="rolse" property="rolse" jdbcType="CHAR" />
  </resultMap>
  
  <select id="getUserPassword" parameterType="String" resultType="String">
  	select password from user where username=#{username}
  </select>
  <select id="getUserRolse" parameterType="String" resultType="String">
  	select rolse from user where username=#{username}
  </select>
</mapper>

然后就是service接口和实现层了

package com.binglian.service;

public interface UserService {

	/**
	 * 根据username 查询密码
	 * @param username
	 * @return
	 */
	String loginPassword(String username);

	/**
	 * 根据username查询角色
	 * @param username
	 * @return
	 */
	String queryRolse(String username);

	/**
	 * 注册
	 * @param username
	 * @param password
	 */
	void regist(String username,String password);
}

 

package com.binglian.service.impl;

import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.binglian.mapper.UserMapper;
import com.binglian.pojo.User;
import com.binglian.service.UserService;

@Service
public class UserServiceImpl implements UserService{

	@Autowired
	private UserMapper userMapper;
	
	@Override
	public String loginPassword(String username) {
		String password=userMapper.getUserPassword(username);
		return password;
	}

	@Override
	public String queryRolse(String username) {
		String rolse=userMapper.getUserRolse(username);
		return rolse;
	}

	@Override
	public void regist(String username, String password) {
		User user=new User();
		// 将用户名作为盐值 
		ByteSource salt = ByteSource.Util.bytes(username); 
		
		/**
		 * 第一个参数 加密方式
		 * 第二是密码
		 * 第三个是盐值
		 * 第四个是加密次数
		 * 然后把变为String型
		 */
		String newpassword = new SimpleHash("MD5", password, salt, 1024).toHex();
		user.setId(null);
		user.setPassword(newpassword);
		user.setUsername(username);
		user.setRolse("admin");
		userMapper.insert(user);
	}

}

 

然后就是我们的自定义Realm

我们从数据库中获取密码和rolse 进行认证,和授权

Subject:主体
访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;
Principal:身份信息
是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。
 

package com.binglian.service.impl;

import static org.hamcrest.CoreMatchers.nullValue;

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.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 com.binglian.service.UserService;

public class CustomRealm extends AuthorizingRealm {

	@Autowired
	private UserService userService;
	
	/**
	 * 授权管理
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		
		//从主体获取用户
		String username=(String)principals.getPrimaryPrincipal();
		
		//从数据库查询用户的角色
		String rolse=userService.queryRolse(username);
		SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
		simpleAuthorizationInfo.addRole(rolse);
		return simpleAuthorizationInfo;
	}
	

	/**
	 * 认证信息
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		
		//从主体获取传过来的用户
		String username=(String)token.getPrincipal();
		
		//通过用户传过来从数据库进行密码
		String password=userService.loginPassword(username);
		
		if(password == null){
			return null;
		}
		//加盐
		ByteSource salt = ByteSource.Util.bytes(username);
        String realmName = this.getName();//获取当前自定义的realm
        
		SimpleAuthenticationInfo simpleAuthenticationInfo=new SimpleAuthenticationInfo(username, password, salt, realmName);
		return simpleAuthenticationInfo;
	}

}

 然后再是shiro配置

Bean一定要加 加入spring容器

当时在@RequiresRoles("admin")无效,需要在里面加两个配置 仔细看配置 这个是授权管理

 

package com.binglian.config;

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

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.binglian.service.impl.CustomRealm;

@Configuration
public class ShiroConfig {
	
	
	/**
	 * 1.构建securityManager环境
		DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
		defaultSecurityManager.setRealm(customRealm);
		
		HashedCredentialsMatcher matcher=new HashedCredentialsMatcher();//加密配置
		matcher.setHashAlgorithmName("MD5");//使用算法md5
		matcher.setHashIterations(1);//加密次数
		
		customRealm.setCredentialsMatcher(matcher);//对自定义Realm进行加密配置
		
	 */
	
	
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
		ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		// 拦截器。匹配原则是最上面的最优先匹配
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        // 配置不会被拦截的链接
        // 配置不会被拦截的链接 顺序判断
     	filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        filterChainDefinitionMap.put("/regist", "anon");
        filterChainDefinitionMap.put("/regist1", "anon");
        filterChainDefinitionMap.put("/login1", "anon");
        
        
        // 剩余请求需要身份认证
        filterChainDefinitionMap.put("/**", "authc");
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/login");
        
//        // 登录成功后要跳转的链接
//     	shiroFilterFactoryBean.setSuccessUrl("/index");
//
//     	//未授权界面;
//     	shiroFilterFactoryBean.setUnauthorizedUrl("/403");
//     	shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
//     		
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
	}
	
	@Bean
    public CustomRealm myShiroRealm(HashedCredentialsMatcher matcher){
        CustomRealm myShiroRealm = new CustomRealm();
        myShiroRealm.setCredentialsMatcher(matcher);
        return myShiroRealm;
    }


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

    /**
     * 密码加密配置
     * 加密次数
     * 并给realm
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        // 采用MD5方式加密
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        // 设置加密次数
        hashedCredentialsMatcher.setHashIterations(1024);
        return hashedCredentialsMatcher;
    }
    
    /**
     *  开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setProxyTargetClass(true);
        return advisorAutoProxyCreator;
    }
  
    /**
     * 开启aop注解支持
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    
}

然后也就是最后一个 控制层  

package com.binglian.controller;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.binglian.service.UserService;

@Controller
public class UserController {

	
	@Autowired
	private UserService userService;

	
	@RequestMapping("/login")
	@ResponseBody
	public String login(@RequestParam("username") String username,
						@RequestParam("password") String password){
		Subject subject=SecurityUtils.getSubject();
		
		UsernamePasswordToken token=new UsernamePasswordToken(username, password);
		
		try {
			subject.login(token);
			if (subject.isAuthenticated()==true) {
				System.out.println("成功");
			}
		} catch (AuthenticationException e) {
			e.printStackTrace();
			System.out.println(e);
		}
		if (subject.hasRole("admin")) {
			return "admin权限";
		}
		
		return "无admin";
	}
	
	@RequestMapping("/regist")
	@ResponseBody
	public String regist(@RequestParam("username") String username,
						@RequestParam("password") String password){
		userService.regist(username, password);
		
		return "注册成功";
	}
	
	@RequestMapping("/list")
	public String list(){
		
		return "list";
	}
	
	@RequiresRoles("admin")
	@RequestMapping("/add")
	@ResponseBody
	public String add(){
		
		return "admin";
		
	}
	@RequiresRoles("user")
	@RequestMapping("/add1")
	@ResponseBody
	public String add1(){
		
		return "用户";
		
	}
	
	@RequestMapping("/regist1")
	public String registindex(){
		return "regist";
	}
	
	@RequestMapping("/login1")
	public String loginindex(){
		return "login";
	}
}

 github地址:https://github.com/binlian/binglian-shiroLoginResit

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值