springboot 与 shiro 整合 (简洁版)
前言:
网上有很多springboot 与 shiro 整合的资料,有些确实写得很好, 对学习shiro和springboot 都有很大的帮助。 有些朋友比较省事, 直接转发或者复制粘贴。但是没有经过自己键盘敲打过的代码, 不是自己的代码。所以, 我这里就来记录一个简洁版的。 不牵涉db的。 废话不多说, 开始。
一. jar包引入
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-autoconfigure --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.4.0</version> <exclusions> <exclusion> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> </exclusion> </exclusions> </dependency> <!-- 由于前面的包里面不包含这个,所以要单独引入, 如果不引入, shiro的权限注解不起作用 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>5.0.7.RELEASE</version> </dependency>
二. MyShiroRealm
public class MyShiroRealm extends AuthorizingRealm { //角色权限和对应权限添加 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取登录用户名 String name = (String) principalCollection.getPrimaryPrincipal(); //添加角色和权限 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //添加角色 simpleAuthorizationInfo.addRole("admin"); //添加权限 simpleAuthorizationInfo.addStringPermission("create"); return simpleAuthorizationInfo; } //用户认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken atoken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) atoken; String name = token.getUsername(); if (name == null) { return null; }//这里验证authenticationToken和simpleAuthenticationInfo的信息 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, "123456", getName()); return simpleAuthenticationInfo; } }
这里由于没有连接数据库, 所以一些动态的地方, 直接写死。
三. 配置文件
@Configuration public class ShiroConfiguration { //将自己的验证方式加入容器 @Bean public MyShiroRealm myShiroRealm() { MyShiroRealm myShiroRealm = new MyShiroRealm(); return myShiroRealm; } //权限管理,配置主要是Realm的管理认证 @Bean public org.apache.shiro.mgt.SecurityManager securityManager(CacheManager cacheManager, SessionManager sessionManager) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setSessionManager(sessionManager); securityManager.setRealm(myShiroRealm()); securityManager.setCacheManager(cacheManager); return securityManager; } //Filter工厂,设置对应的过滤条件和跳转条件 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String,String> map = new HashMap<String, String>(); //登出 map.put("/logout","logout"); map.put("/doLogin", "anon");//对所有用户认证 map.put("/**","authc"); //登录 shiroFilterFactoryBean.setLoginUrl("/login"); //首页 shiroFilterFactoryBean.setSuccessUrl("/index"); //错误页面,认证不通过跳转 shiroFilterFactoryBean.setUnauthorizedUrl("/error"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } //加入注解的使用,不加入这个注解不生效 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } @Bean public CacheManager cacheManager(){ return new EhCacheManager(); } @Bean public SessionDAO sessionDAO(){ return new EnterpriseCacheSessionDAO(); } @Bean public SessionManager sessionManager(SessionDAO sessionDAO){ DefaultWebSessionManager manager = new DefaultWebSessionManager(); manager.setSessionDAO(sessionDAO); manager.setGlobalSessionTimeout(3600000); manager.setSessionValidationInterval(3600000); return manager; } }
四. 控制器
@RestController public class LoginController { @GetMapping("/login") public String login(){ return "need login"; } /登录 @GetMapping("/doLogin") public String doLogin(String uid, String pwd){ //添加用户认证信息 Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(uid,pwd); try{ //进行验证,这里可以捕获异常,然后返回对应信息 subject.login(token); } catch(Exception e){ return "login failed"; } return "login success"; } @RequestMapping(value = "/index") public String index(){ return "index"; } //登出 @RequestMapping(value = "/logout") public String logout(){ return "logout"; } //错误页面展示 @GetMapping("/error") public String error(){ return "error ok!"; } @RequiresRoles("admin") @RequiresPermissions("create") @RequestMapping(value = "/create") public String create(){ return "Create success!"; } @RequiresPermissions("detail") @RequestMapping(value = "/detail") public String detail(){ return "uid"; } }
到这里, 代码就敲完了。
application.yml里面, 只要两行代码:
server:
port: 8080
五. 结果检验
1. 访问页面: http://localhost:8080/doLogin?uid=abc&pwd=123456
2. 访问: http://localhost:8080/create
3. 访问: http://localhost:8080/detail