-
导入相关依赖
-
配置shiro
2.1 配置类
2.2 登录页配置
2.3 shiro默认过滤器 -
自定义Reaml类
-
用户登录
3.1 页面设计
3.2 登录处理
3.3 密码匹配原理
1、导入依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.5.2</version>
</dependency>
2、配置shiro
starter已经做了很多自动配置工作,具体可以参考ShiroAutoConfiguration.java、ShiroBeanAutoConfiguration.java和ShiroWebAutoConfiguration.java这几个文件
@Configuration
public class ShiroConfig {
/**
* 1. 注册自定义Realm
*/
@Bean
public UserRealm realm() {
return new UserRealm();
}
/**
* 2. 配置url过滤器
* 统一做鉴权,即判断哪些请求路径需要用户登录,哪些请求路径不需要用户登录。
* 只做鉴权,不做权限控制,因为权限用注解来实现。
*
* @return
*/
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition shiroFilterChainDefinition = new DefaultShiroFilterChainDefinition();
//不需要认证就能访问
shiroFilterChainDefinition.addPathDefinition("/test/**", "anon");
shiroFilterChainDefinition.addPathDefinition("/login", "anon");
shiroFilterChainDefinition.addPathDefinition("/register", "anon");
shiroFilterChainDefinition.addPathDefinition("/druid/**", "anon");
//需要认证才能访问的
shiroFilterChainDefinition.addPathDefinition("/admin/**", "authc");
shiroFilterChainDefinition.addPathDefinition("/user/**", "authc");
shiroFilterChainDefinition.addPathDefinition("/api/**", "authc");
shiroFilterChainDefinition.addPathDefinition("/**", "authc");
return shiroFilterChainDefinition;
}
/**
* 3 配置security并设置Realm,避免required a bean named 'authorizer' that could not be found.的报错
* @param realm
* @return
*/
@Bean
public DefaultWebSecurityManager securityManager(UserRealm realm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
3、自定义Realm
public class UserRealm extends AuthorizingRealm {
@Resource
UserService userService;
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//第一步:从token中取出用户名,这个用户名是用户在页面输入的信息,传递给token
String username = (String) authenticationToken.getPrincipal();
// 第二步通过用户名从数据库中查询出用户信息
User user = userService.findUserByName(username);
// 第三步 判断
if (user == null) {
throw new UnknownAccountException("账号不存在");
}
if (user.getStatus() == 0) {
throw new LockedAccountException("账号被锁定!请与管理员联系");
}
// 第四步 实例化 SimpleAuthenticationInfo
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user, user.getPassword(), getName()
);
return authenticationInfo;
}
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
}
SimpleAuthenticationInfo 参数说明
参数 | 说明 | 备注 |
---|---|---|
principal | 从数据库中查询的user对象,也可以user对象的用户名。传入的一般都是user对象。 | 必要 |
hashedCredentials | 传的是从数据库中获取的password,然后再与token中的password进行对比,匹配上了就通过,匹配不上就报异常。 | 必要 |
credentialsSalt | 加密盐–用于加密密码对比,为了防止两用户的初始密码是一样的, | 非必要 |
realmName | 从authenticationToken中获取的用户名 | 必要 |
3、登录
在控制层的登录方法中,
创建一个usernamePasswordToken令牌,交由Shiro并调用login()方法进行登录,
如果不抛出任何异常表明登录成功,
如果抛出异常,根据异常种类返回提示出错信息
@RestController
public class LoginController {
@PostMapping("login")
public String login(String username, String password) {
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
try {
SecurityUtils.getSubject().login(usernamePasswordToken);
} catch (IncorrectCredentialsException e) {
throw new CustomShiroException("账号或密码错误");
} catch (ExcessiveAttemptsException e) {
throw new CustomShiroException("操作过于频繁,请稍后在试!");
}
return "success";
}
}
网友评论