最近在用spring boot 做开发,而shiro是一个权限认证工具,所以将shiro整合到springboot中。
首先,maven引入shiro包。这里引入的是1.4的。
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
引入包后,接下来就是进行配置了。
在配置目录下,新建ShiroConfig.java文件,代码:
package com.company.test.config; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; @Configuration public class ShiroConfig { @Bean public ShiroFilterFactoryBean shirFilter(@Qualifier("securityManager") SecurityManager manager) { System.out.println("ShiroConfiguration.shirFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(manager); //拦截器. Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>(); // 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/h/**", "anon"); //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 filterChainDefinitionMap.put("/logout", "logout"); //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> filterChainDefinitionMap.put("/**", "authc"); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/h/login"); // 登录成功后要跳转的链接 shiroFilterFactoryBean.setSuccessUrl("/index"); //未授权界面; shiroFilterFactoryBean.setUnauthorizedUrl("/403"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } //这里设置安全信息认证的方式,由用户自己定义。怎么定义呢,就是根据MyShiroRealm重写。 @Bean public MyShiroRealm myShiroRealm(){ //MyShiroRealm是自己建立的类 MyShiroRealm myShiroRealm = new MyShiroRealm(); myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return myShiroRealm; } //这里主要是设置Realm 就是认证的安全数据 @Bean public SecurityManager securityManager(){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法; //也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源 securityManager.setRealm(myShiroRealm()); return securityManager; } /* * 凭证匹配器 * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 * 所以我们需要修改下doGetAuthenticationInfo中的代码;) * @return */ @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; // hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5("")); return hashedCredentialsMatcher; } }
上面的是基础的配置,然后我们需要配置MyShiroRealm类,代码如下:
package com.company.test.config; import com.company.test.model.User; import com.company.test.server.UserService; 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.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; public class MyShiroRealm extends AuthorizingRealm { @Autowired private UserService userService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } /** * 认证信息.(身份验证) * : * Authentication 是用来验证用户身份 * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("MyShiroRealm.doGetAuthenticationInfo()"); //获取用户的输入的账号. String username = (String)token.getPrincipal(); //取查询数据库中用户的信息 User userInfo = userService.findUser(username); if(userInfo == null){ return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( userInfo, //用户名 userInfo.getPassword(), //密码 getName() //realm name ); return authenticationInfo; } }
至此,shiro基本上算是完成了。当用户输入账号密码时候,即可调用验证代码:
try{ UsernamePasswordToken token = new UsernamePasswordToken(name, pwd); //login方法提交认证,会执行CustomerShiroRealm中的doGetAuthenticationInfo认证方法 SecurityUtils.getSubject().login(token); //认证通过 return true; }catch (AuthenticationException e){ e.getStackTrace(); System.out.println(e.getMessage()); return false; }catch (Exception e){ e.printStackTrace(); return false; }