基本步骤:
添加pom文件依赖
书写自定义的realm
配置shiro
控制层使用
1.添加pom文件依赖
<!-- spring整合shiro -->
<!-- maven会自动添加shiro-core,shiro-web依赖 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
2.书写自定义realm
package com.diit.business.interceptor;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.realm.AuthorizingRealm;
import java.util.ArrayList;
import java.util.List;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
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.diit.business.entity.User;
import com.diit.business.service.AdminService;
/**
*
* @ClassName: MyRealm
* @Description: 自定义realm
* @date
*/
public class MyRealm extends AuthorizingRealm {
//用于用户查询
@Autowired
private AdminService adminService;
/**
* 用于认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (token.getPrincipal() == null) {
return null;
}
//获取用户信息
String name = token.getPrincipal().toString();
String password=new String((char[])token.getCredentials()); //得到密码
return new SimpleAuthenticationInfo(name, password, this.getName());
}
/**
* 用于授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("使用了自定义的realm,用户授权...");
// 获取用户名
// String userName = (String) principals.getPrimaryPrincipal();
// 依据用户名在数据库中查找权限信息
// 角色
List<String> roles = new ArrayList<>();
roles.add("admin");
roles.add("user");
// 权限
List<String> permissions = new ArrayList<>();
permissions.add("admin:select");
permissions.add("admin:delete");
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addStringPermissions(permissions);
simpleAuthorizationInfo.addRoles(roles);
return simpleAuthorizationInfo;
}
}
3.配置shiro
package com.diit.business.interceptor;
import java.util.HashMap;
import java.util.LinkedHashMap;
/**
* Shiro配置Bean
*/
import java.util.Map;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
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.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
/**
*
* @ClassName: ShiroConfig
* @Description: spring整合shiro配置
* @author cheng
* @date 2017年10月10日 上午9:46:43
*/
@Configuration
public class ShiroConfig {
/**
*
* @Title: createMyRealm
* @Description: 自定义的realm
* @return
*/
@Bean
public MyRealm createMyRealm() {
// 加密相关
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// 散列算法
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
// 散列次数
hashedCredentialsMatcher.setHashIterations(1);
MyRealm myRealm = new MyRealm();
//myRealm.setCredentialsMatcher(hashedCredentialsMatcher);
return myRealm;
}
/**
*
* @Title: securityManager
* @Description: 注入自定义的realm
* @Description: 注意方法返回值SecurityManager为org.apache.shiro.mgt.SecurityManager
* ,不要导错包
* @return
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(createMyRealm());
return securityManager;
}
/**
*
* @Title: shirFilter
* @Description: Shiro 的Web过滤器
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/userLogin");
// 登录成功后要跳转的链接,建议不配置,shiro认证成功自动到上一个请求路径
shiroFilterFactoryBean.setSuccessUrl("/index");
// 未授权界面,指定没有权限操作时跳转页面
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
// 过滤器
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 配置不会被过滤的链接 顺序判断
// 过虑器链定义,从上向下顺序执行,一般将/**放在最下边
// 对静态资源设置匿名访问
// anon:所有url都都可以匿名访问
filterChainDefinitionMap.put("/static/**", "anon");
// 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
// authc:所有url都必须认证通过才可以访问
filterChainDefinitionMap.put("/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* @description: shiro web过滤器
* @author cheng
* @dateTime 2018/4/18 15:50
*/
@Bean
public ShiroFilterFactoryBean createShiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/v1/toLoginPage");
// 过滤器
Map<String, String> filterChainDefinitionMap = new HashMap<>();
// 配置不会被过滤的链接 顺序判断
// 过虑器链定义,从上向下顺序执行,一般将/**放在最下边
// 用户注册匿名访问
filterChainDefinitionMap.put("/v1/users/", "anon");
// 管理员登录页面
filterChainDefinitionMap.put("/v1/toLoginPage", "anon");
// 管理员登录
filterChainDefinitionMap.put("/v1/login", "anon");
// 对静态资源设置匿名访问
// anon:所有url都都可以匿名访问
filterChainDefinitionMap.put("/static/**", "anon");
// authc:所有url都必须认证通过才可以访问
filterChainDefinitionMap.put("/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
//加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
代码说明:
1.自定义的realm和注入自定义的realm相当于以前的shiro.ini文件#自定义的realm
myRealm=com.ahut.test.MyRealm
# 注入自定义的realm
securityManager.realms=$myRealm
4.控制层使用
@RestController
public class ShiroAction {
/**
*
* @Title: userLogin
* @Description: 用户登录
* @return
*/
@RequestMapping(value = "/userLogin")
public String userLogin(String username, String password) {
// 以下部分在配置阶段就已经完成,可以直接使用
// 读取配置文件
// Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 获取SecurityManager的实例
// SecurityManager securityManager = factory.getInstance();
// 把 securityManager 的实例绑定到 SecurityUtils 上
// SecurityUtils.setSecurityManager(securityManager);
System.out.println(username + ":" + password);
Subject subject = SecurityUtils.getSubject();
// 自己创建一个令牌,输入用户名和密码
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
try {
subject.login(usernamePasswordToken);
System.out.println("身份认证成功!");
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("账号不存在!");
} catch (LockedAccountException e) {
e.printStackTrace();
System.out.println("账号被锁定!");
} catch (DisabledAccountException e) {
e.printStackTrace();
System.out.println("账号被禁用!");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("凭证/密码错误!");
} catch (ExpiredCredentialsException e) {
e.printStackTrace();
System.out.println("凭证/密码过期!");
} catch (ExcessiveAttemptsException e) {
e.printStackTrace();
System.out.println("登录失败次数过多!");
}
// 是否认证通过
boolean isAuthenticated1 = subject.isAuthenticated();
System.out.println("登录后,是否认证通过:" + isAuthenticated1);
// 退出
subject.logout();
// 是否认证通过
boolean isAuthenticated2 = subject.isAuthenticated();
System.out.println("退出登录后,是否认证通过:" + isAuthenticated2);
return "处理登录";
}
}
可能出现的问题
页面加载css或者js时,出现以下错误:Resource interpreted as Stylesheet but transferred with MIME type text/html
原因:shiro配置原因,对需要认证的资源进行了拦截操作
// authc:所有url都必须认证通过才可以访问
filterChainDefinitionMap.put("/**", "authc");
修改以上代码为:
filterChainDefinitionMap.put("/**", "anon");
完整代码:
/**
* @description: shiro web过滤器
* @author cheng
* @dateTime 2018/4/18 15:50
*/
@Bean
public ShiroFilterFactoryBean createShiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/v1/toLoginPage");
// 过滤器
Map<String, String> filterChainDefinitionMap = new HashMap<>();
// 配置不会被过滤的链接 顺序判断
// 过虑器链定义,从上向下顺序执行,一般将/**放在最下边
// 用户注册匿名访问
filterChainDefinitionMap.put("/v1/users/", "anon");
// 管理员登录页面
filterChainDefinitionMap.put("/v1/toLoginPage", "anon");
// 管理员登录
filterChainDefinitionMap.put("/v1/login", "anon");
// 对静态资源设置匿名访问
// anon:所有url都都可以匿名访问
filterChainDefinitionMap.put("/static/**", "anon");
// authc:所有url都必须认证通过才可以访问
filterChainDefinitionMap.put("/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
转载自:https://blog.csdn.net/qq_28988969/article/details/78190869