Shiro的应用之认证拦挡
Shiro是一个平安开发框架,它把零碎的平安认证等相干性能抽取进去,升高了零碎的开发成本。
一 Shiro实现认证拦挡
步骤: 1 零碎调用subject的login办法将用户信息传递给securityManager 2 securityManager将认证操作委托给Authenticator 3 Authenticator将用户输出的身份信息发送给Realm 4 Realm拜访数据库获取用户信息并将信息封装并返回 5 Authenticator对封装的信息进行身份认证
输出用户信息后登陆到零碎界面
1.须要的依赖
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.3</version></dependency>
2. Shiro的外围配置对象
在springboot中没有为咱们主动配置shiro,所以要手动配置
- 首先创立一个配置类:SpringShiroConfig类;
- 而后在配置类中增加SecurityManager接口对象;
- 在配置类中增加一个ShiroFilterFactoryBean对象;通过此对象实现对匿名拜访和认证拜访
- 代码如下:
package com.py.pj.common.config;import java.util.LinkedHashMap;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.realm.Realm;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @author WL * @version 创立工夫:2020-9-19 13:24:57 * @Description Shiro的外围配置对象 * @Configuration 此注解形容的类是一个配置对象,此对象会交给spring解决 * @Bean 此注解形容的类会被交给spring解决,由spring为咱们创建对象 */@Configurationpublic class SpringShiroConfig { @Bean public SecurityManager securityManager(Realm realm) { DefaultWebSecurityManager dsm = new DefaultWebSecurityManager(); dsm.setRealm(realm); return dsm; } @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean sffBean = new ShiroFilterFactoryBean(); sffBean.setSecurityManager(securityManager); // 设置登录界面url sffBean.setLoginUrl("/doLogin"); LinkedHashMap<String, String> map = new LinkedHashMap<>(); map.put("/bower_components/**", "anon"); map.put("/modules/**", "anon"); map.put("/dist/**", "anon"); map.put("/plugins/**", "anon"); // 用户登录界面容许匿名拜访 map.put("/user/doLogin", "anon"); // 退出登陆 map.put("/doLogout", "logout"); // 除了动态资源,其余的都要认证 map.put("/**", "authc"); sffBean.setFilterChainDefinitionMap(map); return sffBean; }}
3.业务模块实现
本模块的业务在realm模块中实现
- 3.1 依据用户名搜寻用户信息
在SysUserMapper中创立findUserByUsername(String username)办法
SysUser findUserByUsername(String username);mapper映射文件中<select id="findUserByUsername" resultType="com.py.pj.sys.entity.SysUser"> select * from sys_users where username=#{username}</select>
- 3.2 创立realm业务层
package com.py.pj.sys.realm;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authc.credential.CredentialsMatcher;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;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;import org.springframework.stereotype.Service;import com.py.pj.sys.dao.SysUserMapper;import com.py.pj.sys.entity.SysUser;/** * @author WL * @version 创立工夫:2020-9-19 14:15:12 * @Description 受权realm继承认证,所以蕴含认证和受权性能 */@Servicepublic class ShiroUserRealm extends AuthorizingRealm { @Autowired private SysUserMapper sysUserMapper; /** * 设置凭证匹配器匹配规定 */ @Override public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { // 创立凭证匹配器对象 HashedCredentialsMatcher hcm = new HashedCredentialsMatcher(); // 设置加密算法,与用户明码加密算法放弃始终 hcm.setHashAlgorithmName("MD5"); // 设置加密次数 hcm.setHashIterations(1); super.setCredentialsMatcher(hcm); } /** * 受权 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // TODO Auto-generated method stub return null; } /** * 重写认证 token 是从客户端传来的用户的账号信息 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 1.获取用户输出的用户名 UsernamePasswordToken UToken = (UsernamePasswordToken) token; String username = UToken.getUsername(); // 2.基于用户名查用户信息 SysUser user = sysUserMapper.findUserByUsername(username); // 3.判断用户是否存在、是否禁用 if (user == null) { throw new UnknownAccountException(); } if (user.getValid() == 0) { throw new LockedAccountException(); } // 4.封装用户信息 // 盐值是ByteSource格局的所以要转换 ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt()); System.out.println(user.getPassword()); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, // principal (身份) user.getPassword(), // hashedCredentials credentialsSalt, // credentialsSalt getName());// realName return info; }}
- 3.3 controller层
@RequestMapping("doLogin") public JsonResult doLogin(String username,String password) { // 每个用户都是一个subject对象 Subject subject = SecurityUtils.getSubject(); // 对用户进行封装 UsernamePasswordToken token = new UsernamePasswordToken(username,password); // token被传给securityManager;securityManager在传递给Authentication;Authentication再传给realm,从数据库中获取并封装用户信息 subject.login(token); return new JsonResult("OK"); }
至此,借助Shiro实现了用户的登陆认证性能。