ssm整合springboot时,使用的是xml配置文件进行配置,但是在springboot中,没有xml配置文件,就需要手动创建一个配置类,来进行对shiro的配置。
1.创建一个UserRealm,继承 AuthorizingRealm 类,在 重写的 doGetAuthenticationInfo 方法中实现对登录用户的认证,使用获取到的用户名从数据库中查询是否有这个用户,如果有则进行密码的比对认证,如果没有则直接返回null。
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取用户输入的用户名
String username = authenticationToken.getPrincipal().toString();
// 查询数据库
User user = userService.doQueryByName(username);
if (user!=null) {
// 如果user不等于空,进行密码的验证
// 直接加盐的值
ByteSource byteSource = ByteSource.Util.bytes(user.getSalt());
// 第一个参数是用户对象,第二个参数是数据库中查询出来的密码,第三个参数是ByteSource对象,第四个参数是固定的,当前realm名字
return new SimpleAuthenticationInfo(user,user.getUserpwd(),byteSource,this.getName());
}
// 如果user是空,表示没有当前用户,直接返回null,会自动抛出异常
return null;
}
2.创建shiroConfig配置类,来进行对Shiro的配置
/**
* @program: vue-shiro01-java
* @description: shiro配置文件
* @author: mitu_echo
* @create: 2021-07-05 14:04
**/
package com.hyn.vueshiro.config;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
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;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
/**
* 定义加密规则
* @return
*/
@Bean
public CredentialsMatcher credentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
hashedCredentialsMatcher.setHashIterations(2);
return hashedCredentialsMatcher;
}
/**
* 创建自定义 Realm
* @param credentialsMatcher
* @return
*/
@Bean
public UserRealm userRealm(CredentialsMatcher credentialsMatcher) {
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(credentialsMatcher);
return userRealm;
}
/**
* 创建 DefaultWebSecurityManager
* @param userRealm
* @return
*/
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm userRealm) {
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
/**
* 添加过滤器
*
* Shiro内置过滤器,可以实现权限相关的拦截器
* 常用的过滤器:
* anon: 无需认证(登录)可以访问
* authc: 必须认证才可以访问
* user: 如果使用rememberMe的功能可以直接访问
* perms: 该资源必须得到资源权限才可以访问
* roles: 该资源必须得到角色权限才可以访问
*/
// 创建Map对象,存放过滤规则
Map map = new HashMap();
// 设置login请求,无需进行认证
map.put("/login","anon");
// 设置test请求,必须进行认证
map.put("/test","authc");
// 设置被拦截的请求,跳转路径
shiroFilterFactoryBean.setLoginUrl("/NoLogin");
return shiroFilterFactoryBean;
}
}
3.编写controller层,当接收到用户的信息后,进行登录认证操作
/**
* @program: vue-shiro01-java
* @description: 控制层
* @author: mitu_echo
* @create: 2021-07-05 14:19
**/
package com.hyn.vueshiro.controller;
import com.hyn.vueshiro.entity.User;
import com.hyn.vueshiro.service.UserService;
import com.hyn.vueshiro.utils.VueUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private VueUtil vueUtil;
@Autowired
private UserService userService;
@RequestMapping("/doLogin")
private VueUtil doLogin(User user) {
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getUserpwd());
Subject subject = SecurityUtils.getSubject();
try {
// 会进入UserRealm重写的认证方法中
subject.login(token);
} catch (UnknownAccountException uae) {
// 用户名不存在抛出异常
vueUtil.setCode(000);
vueUtil.setMsg("用户不存在");
return vueUtil;
} catch (IncorrectCredentialsException ice) {
// 用户密码错误异常
vueUtil.setCode(000);
vueUtil.setMsg("密码错误");
return vueUtil;
}
vueUtil.setCode(200);
vueUtil.setMsg("登录成功");
return vueUtil;
}
}
4.与vue结合,实现登录的认证
vue中的Login组件
<template>
<div>
<el-form :model="userData" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="username">
<el-input v-model="userData.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="userpwd">
<el-input type="password" v-model="userData.userpwd" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="zhuce()">注册</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
userData: {
username: '',
userpwd: ''
},
rules: {
username: [
{ required: true, message: '请输入用户名', trigger: 'blur' },
{ min: 2, max: 10, message: '长度在 2 到 10 个字符', trigger: 'blur' }
],
userpwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 3, max: 12, message: '长度在 3 到 12 个字符', trigger: 'blur' }
]
},
dialogVisible: false
}
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$axios({
method: 'get',
url: 'user/doLogin',
params: {
username: this.userData.username,
userpwd: this.userData.userpwd
}
}).then( result => {
if (result.data.code!=200) {
this.$message.error(result.data.msg);
} else {
this.$message.success(result.data.msg);
this.$router.push("/homePage")
}
this.userData = {}
})
} else {
this.$message.error("输入有误");
return false;
}
})
}
}
</script>
<style scoped>
</style>