<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.3.2version>
dependency>
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;
}
}
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;
}
}
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;
}
}
}
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满足所有权限
在过滤器链中配置
@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:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗
try {
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole("user")){
//TODO
}
} catch (AuthorizationException e) {
e.printStackTrace();
}
在登陆成功以后,设置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();
}