springboot集成shiro的简单实现
注意:
1.shiro需要自行在doGetAuthenticationInfo方法中进行账号密码的校验
2.ip+端口形式访问页面会被shiro拦截,如果没有登录会被重定向到login页面,如果登录会被重定向到index页面(需要配置)
3.登录成功后index页面跳转由shiro内部实现(需要配置)
4.退出登录操作由shiro内部实现(需要配置)
5.shiro的权限控制(按钮级别),为了在thymeleaf里使用shiro的标签的bean,需要在shiro中注入ShiroDialect(需要添加maven),否则无法进入doGetAuthorizationInfo方法!
流程:
当访问项目时会被shiro拦截进行登录校验,如果未登录会被重定向到登录页,如果登录直接放行方法(如果是ip+端口的形式访问会被重定向到首页)
方法:
获取shiro管理的对象方法:
User user = (User) SecurityUtils.getSubject().getPrincipal();
@Controller
public class LoginController {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
// 首页跳转
@GetMapping("/")
String toIndex() {
return "index";
}
// 登录跳转
@GetMapping("/login")
String login() {
return "login";
}
// 登录
@PostMapping("/ajaxLogin")
@ResponseBody
String ajaxLogin(String username, String password) {
try {
//收集实体/凭据信息
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
Subject subject = SecurityUtils.getSubject();
subject.login(token);
} catch (Exception e) {
return "error";
}
return "success";
}
// 测试
@GetMapping("/test")
@RequiresPermissions("companyUser:user:save")
String test(RedirectAttributes redirectAttributes) {
redirectAttributes.addAttribute("a", "a");
redirectAttributes.addAttribute("b", "b");
return "redirect:/test2";
}
// 测试
@GetMapping("/test2")
@ResponseBody
User test2(String a , String b ) {
System.out.println("a:"+a +"----------"+"b:"+b );
User user = (User) SecurityUtils.getSubject().getPrincipal();
return user;
}
}
//自定义验证器(必要的)
public class MyRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// System.out.println("==================================================================授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//存放可放行的权限
Set<String> str = new HashSet<>();
str.add("companyUser:user:save");
info.setStringPermissions(str);
return info;
}
//验证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// System.out.println("==================================================================验证");
UsernamePasswordToken user = (UsernamePasswordToken) authenticationToken;
char[] pd = user.getPassword();
String password = String.valueOf(pd);
String username = user.getUsername();
if (!"admin".equals(username)||!"123456".equals(password)) {
throw new IncorrectCredentialsException("账号或密码不正确");
}
User user = new User();
user.setPassword(password);
user.setUsername(username);
//第一个参数用来存放在session中的信息
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
return info;
}
}
//注入验证器(必要的)
@Configuration
public class ShiroConfiguration {
//将自己的验证方式加入容器
@Bean
public MyRealm myShiroRealm() {
MyRealm myRealm = new MyRealm();
return myRealm;
}
/**
* ShiroDialect,为了在thymeleaf里使用shiro的标签的bean
* html中使用方法:shiro:hasPermission
* Maven中添加:
* <dependency>
* <groupId>com.github.theborakompanioni</groupId>
* <artifactId>thymeleaf-extras-shiro</artifactId>
* <version>2.0.0</version>
* </dependency>
*
* @return
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
//权限管理,配置主要是Realm的管理认证
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> map = new HashMap<String, String>();
//放行路径
map.put("/ajaxLogin","anon");
//登出
map.put("/logout","logout");
//对所有用户认证
map.put("/**","authc");
//登录
shiroFilterFactoryBean.setLoginUrl("/login");
//首页
shiroFilterFactoryBean.setSuccessUrl("/index");
//错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
登录页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form id="loginForm">
账号:<input type="text" placeholder="请输入账号" name="username">
密码:<input type="text" placeholder="请输入密码" name="password">
<input type="button" id="loginBut" value="登录">
</form>
</body>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
$("#loginBut").click(function () {
$.ajax({
type: "POST",
url: "/ajaxLogin",
data: $("#loginForm").serialize(),
success: function (r) {
if ("success" == r) {
location.href="/"
}else{
alert("账号或密码不正确!");
}
}
});
})
</script>
</html>
首页(权限测试页)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/test" shiro:hasPermission="companyUser:user:save">登录成功测试(有权限)</a>
<a href="/test" >登录成功测试(无权限)</a>
</body>
</html>
//User对象
/**@Date注解
* maven添加
* <dependency>
* <groupId>org.projectlombok</groupId>
* <artifactId>lombok</artifactId>
* </dependency>
*/
@Data
public class User implements Serializable {
private String username;
private String password;
}