Shiro简介
Apache Shiro是一个强大且易用的java认证、授权、加密和会话管理的框架,主要有三个核心的组件:Subject,SecurityManager和Realms。
Subject:不仅指人,还可以是第三方进程、后台账户等,它表示跟系统或软件交互的东西。
SecurityManager:它是Shiro框架的核心组件,管理组件实例和提供安全服务的各种管理。
Realm:Shiro与应用数据交互的桥梁,可以理解为spring中的dao层。
创建SpringBoot项目
在IDEA中选择File->New->Project->Spring Initialiar,创建如下结构的maven项目
SpringBoot整合Swagger
引入依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.7.0</version>
</dependency>
Swagger配置类
@Configuration
public class SwaggerConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.manage.controller"))
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("voyage-manage")
.description("java学习资料后台")
.termsOfServiceUrl("voyage@163.com")
.version("1.0")
.build();
}
}
效果
SpringBoot整合Shiro
引入依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
Shiro配置类
@Configuration
public class ShiroConfig {
@Bean("shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置securityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// // 登录的url
// shiroFilterFactoryBean.setLoginUrl("/login");
// // 登录成功后跳转的url
// shiroFilterFactoryBean.setSuccessUrl("/index");
// // 未授权url
// shiroFilterFactoryBean.setUnauthorizedUrl("/403");
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 定义filterChain,静态资源不拦截
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
// druid数据源监控页面不拦截
filterChainDefinitionMap.put("/swagger-ui.html/**", "anon");
// 配置退出过滤器,其中具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**", "anon");
// // 除上以外所有url都必须认证通过才可以访问,未通过认证自动访问LoginUrl
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean("securityManager")
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(mangeRealm());
// //关闭shiro自带的token
// DefaultSubjectDAO defaultSubjectDAO = new DefaultSubjectDAO();
// DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
// defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
// defaultSubjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
// securityManager.setSubjectDAO(defaultSubjectDAO);
return securityManager;
}
// @Bean
// @DependsOn("lifecycleBeanPostProcessor")
// public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
// DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
// defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
// return defaultAdvisorAutoProxyCreator;
// }
//
// @Bean
// public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
// return new LifecycleBeanPostProcessor();
// }
//
// @Bean
// public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
// AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
// advisor.setSecurityManager(securityManager);
// return advisor;
// }
@Bean
public MangeRealm mangeRealm() {
MangeRealm mangeRealm = new MangeRealm();
mangeRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return mangeRealm;
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5"); //MD5散列加密
hashedCredentialsMatcher.setHashIterations(2); //散列2次
return hashedCredentialsMatcher;
}
Realm
@Slf4j
public class MangeRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Autowired
private RedisService redisService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
log.info("用户认证开始------" + username);
UserDO userDO = userService.fetUserByUserName(username);
if (userDO == null) {
throw new UnknownAccountException("用户名或密码错误");
}
SecurityUtils.getSubject().getSession().setAttribute("user", userDO);
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userDO.getUsername(), userDO.getPassword(),
ByteSource.Util.bytes(userDO.getSalt()), getName());
return authenticationInfo;
}
}
本文主要的目的在演示Shiro的应用,关心原理的同学可以看这篇文章shiro的原理,上面的代码采用了MD5散列两次,附带盐值得加密方法,所以在用户保存的时候,就要对密码进行加密。