集成shiro
springboot+shiro
实现功能:
1.用户未登录时,只能访问用户登录页面。访问其他页面会被拦截,自动跳转到登录页面。
2.用户登录成功后,跳转到首页。可随意访问其他页面。
首先引入shiro依赖
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
配置shiro文件。使用@Configuration注解代替xml配置文件
package com.cww.shiro;
import java.util.LinkedHashMap;
import java.util.Map;
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;
@Configuration //Configuration注解,代替xml配置文件
public class ShiroConfig {
@Bean //类似xml中一个bean的定义 <bean id="getXXX" class="Shiro....class">
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
shiroFilterFactoryBean.setLoginUrl("/toLogin");
/*
* shiro过滤器
* anon:无需认证,无登录即可访问
* authc:必须认证,登录后才可访问
* user:使用rememberMe才可访问,rememberMe类似session。
* perms:必须的到资源权限才可访问
* role:必须得到角色才可访问
*/
Map<String,String> filterMap = new LinkedHashMap<>();
//设置没有登录时可访问的url,即进行登录接口与静态资源下的js文件
filterMap.put("/login", "anon");
filterMap.put("/js/*", "anon");
//从上往下进行过滤,/*表示过滤全部。即除了/login与/toLogin链接.其他链接都需要进行登录才可访问
filterMap.put("/*", "authc");
//设置过滤链
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
//创建DefaultWebSecurityManager类
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm){
DefaultWebSecurityManager d = new DefaultWebSecurityManager();
d.setRealm(myRealm);
return d;
}
//创建Realm
@Bean(name = "myRealm")
public MyRealm getMyRealm(){
return new MyRealm();
}
}
编写MyRealm文件、shiro用户的认证、授权操作
package com.cww.shiro;
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.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import com.cww.user.dao.UserDao;
import com.cww.user.entity.User;
public class MyRealm extends AuthorizingRealm{
@Autowired
UserDao userDao;
//授权处理
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
//授权操作、没有分角色系统。暂时为空
return null;
}
//认证处理
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken a) throws AuthenticationException {
// 编写Shiro判断逻辑,判断账号和密码
// 1、判断账号
UsernamePasswordToken token = (UsernamePasswordToken) a;
User user = userDao.findByUsername(token.getUsername());
if (user == null) {
// 账号错误,Shiro底层会抛出UnknownAccountException异常
return null;
}
// 2、判断密码
return new SimpleAuthenticationInfo("", user.getPassword(), "");
}
}
编写接口
package com.cww.user.controller;
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.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.cww.user.service.UserService;
@Controller
public class UserController {
@Autowired
UserService userService;
/*
* 登录页面
*/
@RequestMapping("/toLogin")
public String toLogin(Model m){
return "login";
}
/*
* 首页
*/
@RequestMapping("/index")
public String index(Model m){
return "index";
}
/*
* 用户登录
*/
@RequestMapping("/login")
@ResponseBody
public String login(Model m,String username,String password){
//1.获取Subject
Subject subject = SecurityUtils.getSubject();
//2.封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
//3.执行登录
try{
//登录成功
subject.login(token);
return "登录成功";
}catch(UnknownAccountException e){
return "账号不存在!";
}catch (IncorrectCredentialsException exception) {
return "密码错误!";
}
}
/*
* 登出
*/
@SuppressWarnings("finally")
@RequestMapping("/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
try {
subject.logout();
} catch (Exception ex) {
ex.printStackTrace();
} finally {
return "login";
}
}
}
dao层增加接口
User findByUsername(String username);
登录页面login.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>login</title>
<script type="text/javascript" th:src="@{/js/jquery-3.4.1-min.js}"></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
body{
text-align:center;
}
</style>
</head>
<body>
<table>
<tr>
<td>账号:</td>
<td><input type="text" id="username" /></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" id="password" /></td>
</tr>
<tr>
<td colspan="2"><button id="login">登录</button></td>
</tr>
</table>
</body>
<script type="text/javascript">
$('#login').click(function(){
$.ajax({
url:'http://localhost:8080/login',
data:{
username: $('#username').val(),
password: $('#password').val(),
},
success:function(r){
if(r=="登录成功")
location.href = "http://localhost:8080/index";
else
alert(r);
}
})
})
</script>
</html>
首页index.html
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>index</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style>
body{
text-align:center;
}
</style>
</head>
<body>
<h1>welcome to my site </h1>
<p><a href="logout">登出</a></p>
</body>
</html>
启动项目不登录时,访问index会自动跳转到登录页面。登录成功会跳转到首页
项目的目录