实用向-shiro+spingboot入门

一 shiro使用

1.1 shiro依赖

<dependency>
   <groupId>org.apache.shirogroupId>
   <artifactId>shiro-springartifactId>
   <version>1.3.2version>
dependency>

1.2 shiro配置

package com.xk.mymall.shiro;

import com.xk.mymall.shiro.CustomRealm;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
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 ShiroConfig {

    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager,Map<String, String> filterChainDefinitionMap) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //1. 自定义安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //2. 自定义过滤器链
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

    @Bean
    public Map<String, String> filterChainDefinitionMap(){
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //1.定义哪些请求需要认证
        filterChainDefinitionMap.put("/**", "authc");
        return filterChainDefinitionMap;
    }

    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        //1.设置自定义Relam来验证登陆结果
        defaultSecurityManager.setRealm(customRealm());
        return defaultSecurityManager;
    }

    @Bean
    public CustomRealm customRealm() {
        CustomRealm customRealm = new CustomRealm();
        //principle加密
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setHashIterations(2);
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        customRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return customRealm;
    }
}

二 shiro认证

2.1 认证流程

实用向-shiro+spingboot入门_第1张图片

2.2 自定义Token

package com.nriat.core.shiro;

import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.HostAuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;

public class PhoneToken  extends UsernamePasswordToken {

    private String phoneNumber;
    private String verifyCode;

    @Override
    public Object getPrincipal() {
        return getPhoneNumber();
    }

    @Override
    public Object getCredentials() {
        return getVerifyCode();
    }



    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getVerifyCode() {
        return verifyCode;
    }

    public void setVerifyCode(String verifyCode) {
        this.verifyCode = verifyCode;
    }

    @Override
    public String getHost() {
        return null;
    }
}

2.3 自定义Relam

package com.nriat.shiro;

import com.nriat.core.redis.service.RedisService;
import com.nriat.core.shiro.PhoneToken;
import com.nriat.utils.GlobalParam;
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.springframework.beans.factory.annotation.Autowired;

import com.nriat.core.system.model.User;
import com.nriat.core.system.service.UserService;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class PhoneRealm extends AuthorizingRealm {

	@Autowired
	private UserService userService;

	@Autowired
	private RedisService redisService;
	
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		String phoneNumber = (String) principals.getPrimaryPrincipal();

		User user = userService.findByPhoneNumber(phoneNumber);
		if(user!= null){
			SimpleAuthorizationInfo result = new SimpleAuthorizationInfo();
			Set<String> roles = new HashSet<>();
			roles.add(user.getRoleId().toString());
			result.setRoles(roles);
			return result;
		}else{
			return null;
		}
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {

		if (token instanceof PhoneToken) {
			String phoneNumber =  (String) token.getPrincipal();
			User userFind = userService.findByPhoneNumber(phoneNumber);
			if (userFind != null) {
				String verifyCode = (String) redisService.get(GlobalParam.Phone_PREFIX_CODE+phoneNumber);
				AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(userFind.getPhoneNumber(), verifyCode, this.getClass().getName());
				return authcInfo;
			} else {		
				return null;
			}
		} else {
			return null;
		}
	}

}

三 shiro鉴权

3.1 注解实现权限控制

shiroConfig中添加以下配置,启动注解

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

@RequiresAuthentication 验证是否登录

@RequiresRoles 验证是否拥有角色

@RequiresRoles(value = { "1","2","3"},logical= Logical.OR)
value:角色或角色数组
logical:Logical.OR拥有其中一种角色,Logical.AND满足所有角色

@RequiresPermissions 验证是否拥有权限

@RequiresPermissions(value = { "1:read","2:write","3:read"},logical= Logical.AND)
value:权限或权限数组
logical:Logical.OR拥有其中一种权限,Logical.AND满足所有权限

3.2 URL过滤实现权限控制

在过滤器链中配置

@Bean
    public Map<String, String> filterChainDefinitionMap(){
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        //1.定义哪些请求需要认证
        filterChainDefinitionMap.put("/**", "authc");
        return filterChainDefinitionMap;
    }
anon: /admins/**=anon 没有参数,表示可以匿名使用。
authc: /admins/user/**=authc 表示需要认证(登录)才能使用,没有参数
roles:/admins/user/**=roles[admin],参数可以写多个,每个参数通过才算通过。
perms:/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗

3.3 代码块实现权限控制

try {
    Subject subject = SecurityUtils.getSubject();
    if(subject.hasRole("user")){
        //TODO
    }
} catch (AuthorizationException e) {
    e.printStackTrace();
}

四 shiro其他操作

4.1 获取用户登陆信息

在登陆成功以后,设置session

subject.login(token);
//将用户信息放入session
if(subject.isAuthenticated()){
	Session session = subject.getSession();
	session.setAttribute(CacheUtils.SESSION_USER,findByPhoneNumber(phoneNumber));
}

封装获取user方法

public static Long getCurrentUserId(){
	Subject subject = SecurityUtils.getSubject();
	Session session =  subject.getSession();
	User user = (User) session.getAttribute(CacheUtils.SESSION_USER);
	return user.getId();
}

你可能感兴趣的:(实用向-shiro+spingboot入门)