
引入依赖
<!--引入shiro整合springboot依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.5.3</version>
</dependency>
<!--引入shiro和ehcache -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.5.3</version>
</dependency>
自定义realm
package com.lzy.shiro.realm;
import com.lzy.pojo.SysPerm;
import com.lzy.pojo.SysRole;
import com.lzy.pojo.SysUser;
import com.lzy.service.SysUserService;
import com.lzy.shiro.salt.MyByteSource;
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.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.List;
//自定义realm
public class CustomerRealm extends AuthorizingRealm {
@Resource
private SysUserService sysUserService;
// 授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//获取身份信息
String primaryPrincipal = (String) principals.getPrimaryPrincipal();
//根据主身份信息获取角色 和 权限信息
SysRole role = sysUserService.findRolesByUserName(primaryPrincipal);
//授权角色信息
//拿到授权器
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addRole(role.getName());
//权限信息
List<SysPerm> perms = sysUserService.findPermsByRoleId(role.getId());
if(!CollectionUtils.isEmpty(perms)){
perms.forEach(perm->{
System.out.println(perm.getName());
simpleAuthorizationInfo.addStringPermission(perm.getName());
});
}
return simpleAuthorizationInfo;
}
// 认证方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//根据身份信息
String principal = (String) token.getPrincipal();
SysUser user = sysUserService.findByUserName(principal);
if(!ObjectUtils.isEmpty(user)){
return new SimpleAuthenticationInfo(principal,user.getPassword(),
new MyByteSource(user.getSalt()),
this.getName());
}
return null;
}
}
shiro配置文件
package com.lzy.shiro.config;
import java.util.HashMap;
import java.util.Map;
import com.baomidou.mybatisplus.extension.api.R;
import com.lzy.shiro.realm.CustomerRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
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;
//用来整合shiro框架相关配置类
@Configuration
public class ShiroConfig {
// shiroFilter 负责拦截所有请求
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 给filter设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
// 配置系统受限资源
// 配置系统公共资源
Map<String, String> map = new HashMap<String, String>();
map.put("/assets/**", "anon");
map.put("/bootstrap-3.3.7/**", "anon");
map.put("/common/**", "anon");
map.put("/css/**", "anon");
map.put("/img/**", "anon");
map.put("/js/**", "anon");
map.put("/template/**", "anon");
map.put("/sys/login/login.page", "anon");// anon 设置为公共资源
map.put("/sys/login/register.page", "anon");// anon 设置为公共资源
// / 受限资源 不受限的资源放在上面
map.put("/", "authc");// authc 请求这个资源需要认证和授权 /拦截所有资源
// shiroFilterFactoryBean.setLoginUrl("/sys/login/login.page");
// shiroFilterFactoryBean.setSuccessUrl("/sys/admin/admin.page");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
// 2.创建安全管理器
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
// 给安全管理器设置realm
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
// 3.创建自定义realm
@Bean
public CustomerRealm getRealm() {
CustomerRealm customerRealm = new CustomerRealm();
// 修改凭证校验匹配器
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
// 设置加密算法为md5
credentialsMatcher.setHashAlgorithmName("MD5");
// 设置散列次数
credentialsMatcher.setHashIterations(1024);
customerRealm.setCredentialsMatcher(credentialsMatcher);
return customerRealm;
}
}
自定义salt
package com.lzy.shiro.salt;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.codec.Hex;
import org.apache.shiro.util.ByteSource;
//自定义salt实现 实现序列化接口
public class MyByteSource implements ByteSource,Serializable {
private byte[] bytes;
private String cachedHex;
private String cachedBase64;
public MyByteSource(){
}
public MyByteSource(byte[] bytes) {
this.bytes = bytes;
}
public MyByteSource(char[] chars) {
this.bytes = CodecSupport.toBytes(chars);
}
public MyByteSource(String string) {
this.bytes = CodecSupport.toBytes(string);
}
public MyByteSource(ByteSource source) {
this.bytes = source.getBytes();
}
public MyByteSource(File file) {
this.bytes = (new BytesHelper()).getBytes(file);
}
public MyByteSource(InputStream stream) {
this.bytes = (new BytesHelper()).getBytes(stream);
}
public static boolean isCompatible(Object o) {
return o instanceof byte[] || o instanceof char[] || o instanceof String || o instanceof ByteSource || o instanceof File || o instanceof InputStream;
}
public byte[] getBytes() {
return this.bytes;
}
public boolean isEmpty() {
return this.bytes == null || this.bytes.length == 0;
}
public String toHex() {
if (this.cachedHex == null) {
this.cachedHex = Hex.encodeToString(this.getBytes());
}
return this.cachedHex;
}
public String toBase64() {
if (this.cachedBase64 == null) {
this.cachedBase64 = Base64.encodeToString(this.getBytes());
}
return this.cachedBase64;
}
public String toString() {
return this.toBase64();
}
public int hashCode() {
return this.bytes != null && this.bytes.length != 0 ? Arrays.hashCode(this.bytes) : 0;
}
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof ByteSource) {
ByteSource bs = (ByteSource)o;
return Arrays.equals(this.getBytes(), bs.getBytes());
} else {
return false;
}
}
private static final class BytesHelper extends CodecSupport {
private BytesHelper() {
}
public byte[] getBytes(File file) {
return this.toBytes(file);
}
public byte[] getBytes(InputStream stream) {
return this.toBytes(stream);
}
}
}
登录验证
// 登录用户
@RequestMapping("/login.json")
public String login(String telephone, String password){
try {
// 获取主体对象
Subject subject = SecurityUtils.getSubject();
// System.out.println(telephone+" "+ password);
// 认证token
subject.login(new UsernamePasswordToken(telephone, password));
return "admin";
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用户名错误!");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密码错误!");
} catch (Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
return "login";
}
页面如此
