New file |
| | |
| | | package com.example.springboot.security.config; |
| | | |
| | | import com.example.springboot.security.JWTRealm; |
| | | import com.example.springboot.security.NoSessionFilter; |
| | | import com.example.springboot.security.StatelessDefaultSubjectFactory; |
| | | import com.example.springboot.security.UserRealm; |
| | | import org.apache.shiro.authc.credential.HashedCredentialsMatcher; |
| | | import org.apache.shiro.codec.Base64; |
| | | import org.apache.shiro.mgt.DefaultSessionStorageEvaluator; |
| | | import org.apache.shiro.mgt.DefaultSubjectDAO; |
| | | import org.apache.shiro.spring.LifecycleBeanPostProcessor; |
| | | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; |
| | | import org.apache.shiro.spring.web.ShiroFilterFactoryBean; |
| | | import org.apache.shiro.web.mgt.CookieRememberMeManager; |
| | | import org.apache.shiro.web.mgt.DefaultWebSecurityManager; |
| | | import org.apache.shiro.web.servlet.SimpleCookie; |
| | | import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | import org.springframework.context.annotation.DependsOn; |
| | | |
| | | import javax.servlet.Filter; |
| | | import java.util.Arrays; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.Map; |
| | | |
| | | @Configuration |
| | | public class ShiroConfig { |
| | | |
| | | |
| | | /** |
| | | * Shiro生命周期处理器 |
| | | * |
| | | * @return |
| | | */ |
| | | @Bean |
| | | public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { |
| | | return new LifecycleBeanPostProcessor(); |
| | | } |
| | | |
| | | /** |
| | | * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 |
| | | * DefaultAdvisorAutoProxyCreator的顺序必须在shiroFilterFactoryBean之前,不然SecurityUtils.getSubject().getPrincipal()获取不到参数 |
| | | * |
| | | * @return |
| | | */ |
| | | @Bean |
| | | @DependsOn({"lifecycleBeanPostProcessor"}) |
| | | public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() { |
| | | DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); |
| | | advisorAutoProxyCreator.setProxyTargetClass(true); |
| | | return advisorAutoProxyCreator; |
| | | } |
| | | |
| | | @Bean |
| | | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { |
| | | AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); |
| | | authorizationAttributeSourceAdvisor.setSecurityManager(defaultSecurityManager()); |
| | | return authorizationAttributeSourceAdvisor; |
| | | } |
| | | |
| | | @Bean(name = "shiroFilterFactoryBean") |
| | | public ShiroFilterFactoryBean shiroFilterFactoryBean() { |
| | | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); |
| | | shiroFilterFactoryBean.setSecurityManager(defaultSecurityManager()); |
| | | |
| | | // 过滤规则 |
| | | Map<String, String> linkedHashMap = new LinkedHashMap<>(); |
| | | // 无状态登录情况下关闭了shiro中的session,导致所有需要加上authc接口请求时候都会报错, |
| | | // 所以使用@RequiresRoles,@RequiresPermissions注解,aop方式实现接口的权限校验 |
| | | |
| | | /* 添加shiro的内置过滤器,自定义url规则 |
| | | * Shiro自带拦截器配置规则 |
| | | * rest:比如/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等 |
| | | * port:比如/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString是你访问的url里的?后面的参数 |
| | | * perms:比如/admins/user/**=perms[user:add:*],perms参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,比如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法 |
| | | * roles:比如/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,比如/admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。//要实现or的效果看http://zgzty.blog.163.com/blog/static/83831226201302983358670/ |
| | | * anon:比如/admins/**=anon 没有参数,表示可以匿名使用 |
| | | * authc:比如/admins/user/**=authc表示需要认证才能使用,没有参数 |
| | | * authcBasic:比如/admins/user/**=authcBasic没有参数表示httpBasic认证 |
| | | * ssl:比如/admins/user/**=ssl没有参数,表示安全的url请求,协议为https |
| | | * user:比如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查 |
| | | * 详情见文档 http://shiro.apache.org/web.html#urls- |
| | | * */ |
| | | // 用户权限 |
| | | // linkedHashMap.put("/api/user/selectPage", "perms[user:select]"); |
| | | // linkedHashMap.put("/api/user/selectById", "perms[user:select]"); |
| | | // linkedHashMap.put("/api/user/updateById", "perms[user:update]"); |
| | | // linkedHashMap.put("/api/user/removeByIds", "perms[user:delete]"); |
| | | // // 商品权限 |
| | | // linkedHashMap.put("/api/product/deleteBatchIds", "perms[product:delete]"); |
| | | // linkedHashMap.put("/api/product/updateById", "perms[product:update]"); |
| | | // linkedHashMap.put("/api/product/insert", "perms[product:add]"); |
| | | // |
| | | // // 角色权限 |
| | | // linkedHashMap.put("/api/role/saveOrUpdate", "perms[role:add,role:update]"); |
| | | // linkedHashMap.put("/api/role/removeByIds", "perms[role:delete]"); |
| | | // linkedHashMap.put("/api/role/getById", "perms[role:select]"); |
| | | // linkedHashMap.put("/api/role/selectPage", "perms[role:select]"); |
| | | // |
| | | // // 菜单权限 |
| | | // linkedHashMap.put("/api/menuList/removeByIds", "perms[menuList:delete]"); |
| | | // linkedHashMap.put("/api/menuList/saveOrUpdate", "perms[menuList:add,menuList:update]"); |
| | | // |
| | | // // 订单权限 |
| | | // linkedHashMap.put("/api/order/deleteBatchIds", "perms[order:delete]"); |
| | | // linkedHashMap.put("/api/order/updateById", "perms[order:update]"); |
| | | // |
| | | // // 授权的权限 |
| | | // linkedHashMap.put("/api/rolePermission/saveOrUpdate", "perms[rolePermission:add]"); |
| | | // linkedHashMap.put("/api/rolePermission/removeByIds", "perms[rolePermission:delete]"); |
| | | |
| | | // 自定义过滤器 |
| | | HashMap<String, Filter> filterHashMap = new HashMap<>(); |
| | | filterHashMap.put("jwt", new NoSessionFilter()); |
| | | shiroFilterFactoryBean.setFilters(filterHashMap); |
| | | // 登录之后才可以请求的接口 |
| | | linkedHashMap.put("/api/**", "jwt"); |
| | | shiroFilterFactoryBean.setFilterChainDefinitionMap(linkedHashMap); |
| | | return shiroFilterFactoryBean; |
| | | } |
| | | |
| | | @Bean |
| | | public DefaultWebSecurityManager defaultSecurityManager() { |
| | | DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); |
| | | defaultWebSecurityManager.setRealms(Arrays.asList(userRealm(), jwtRealm())); |
| | | // 禁用shiro中的session |
| | | DefaultSubjectDAO defaultSubjectDAO = new DefaultSubjectDAO(); |
| | | DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator(); |
| | | defaultSessionStorageEvaluator.setSessionStorageEnabled(false); |
| | | defaultSubjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator); |
| | | defaultWebSecurityManager.setSubjectDAO(defaultSubjectDAO); |
| | | defaultWebSecurityManager.setSubjectFactory(subjectFactory()); |
| | | return defaultWebSecurityManager; |
| | | } |
| | | |
| | | /** |
| | | * 登录的认证和授权 |
| | | * |
| | | * @return |
| | | */ |
| | | @Bean |
| | | public UserRealm userRealm() { |
| | | UserRealm userRealm = new UserRealm(); |
| | | userRealm.setCredentialsMatcher(hashedCredentialsMatcher()); |
| | | return userRealm; |
| | | } |
| | | |
| | | /** |
| | | * token的认证和授权 |
| | | * |
| | | * @return |
| | | */ |
| | | @Bean |
| | | public JWTRealm jwtRealm() { |
| | | return new JWTRealm(); |
| | | } |
| | | |
| | | @Bean |
| | | public StatelessDefaultSubjectFactory subjectFactory() { |
| | | return new StatelessDefaultSubjectFactory(); |
| | | } |
| | | |
| | | /* |
| | | * 凭证匹配器 由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 |
| | | */ |
| | | @Bean |
| | | public HashedCredentialsMatcher hashedCredentialsMatcher() { |
| | | HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); |
| | | hashedCredentialsMatcher.setHashAlgorithmName("MD5");// 散列算法:这里使用MD5算法; |
| | | hashedCredentialsMatcher.setHashIterations(1024);// 散列的次数,比如散列两次,相当于MD5(MD5("")); |
| | | return hashedCredentialsMatcher; |
| | | } |
| | | |
| | | @Bean |
| | | public CookieRememberMeManager cookieRememberMeManager() { |
| | | CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); |
| | | SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); |
| | | simpleCookie.setMaxAge(259200000); |
| | | cookieRememberMeManager.setCookie(simpleCookie); |
| | | cookieRememberMeManager.setCipherKey(Base64.decode("6ZmI6I2j5Y+R5aSn5ZOlAA==")); |
| | | return cookieRememberMeManager; |
| | | } |
| | | } |