前端页面
<div style="margin-left:auto; margin-right:auto;width:200px;height:100px;">
<form th:action="@{/login}">
<h1 style="text-align:center">登录</h1><br/>
<p style="color:red;" th:text="${msg}"></p>
用户名:<input type="text" name="username"><br/>
密码: <input type="password" name="password"><br/>
<input type="checkbox" name="rememberMe"><span>记住密码</span>
<br/>
<input type="submit" value="登录"><br/>
</form>
</div>
实体类User.java(实体类需要序列化)
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable{
private static final long serialVersionUID = 69667703L;
private String userName;
private String password;
private String perms;
}
ShiroConfig.java
package com.loey.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
//声明为配置类
@Configuration
public class ShiroConfig {
//创建 ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterMap = new LinkedHashMap<String,String>();
/*
添加Shiro内置过滤器,常用的有如下过滤器:
anon: 无需认证就可以访问
authc: 必须认证才可以访问
user: 如果使用了记住我功能就可以直接访问
perms: 拥有某个资源权限才可以访问
role: 拥有某个角色权限才可以访问
*/
// filterMap.put("/user/add","authc");
// filterMap.put("/user/update","authc");
//授权过滤器
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/update","perms[user:update]");
filterMap.put("/user/*","user");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");
//修改要跳转的login页面
shiroFilterFactoryBean.setLoginUrl("/toLogin");
return shiroFilterFactoryBean;
}
//创建 DefaultWebSecurityManager
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm,@Qualifier("cookieRememberMeManager") CookieRememberMeManager cookieRememberMeManager){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联Realm
securityManager.setRealm(userRealm);
securityManager.setRememberMeManager(cookieRememberMeManager);
return securityManager;
}
@Bean(name = "cookie")
public SimpleCookie getCookie(){
SimpleCookie cookie = new SimpleCookie("rememberMe");
cookie.setHttpOnly(true);
cookie.setMaxAge(604800);
return cookie;
}
@Bean("cookieRememberMeManager")
public CookieRememberMeManager getCookieRememberMeManager(@Qualifier("cookie") SimpleCookie cookie){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(cookie);
// rememberMe cookie加密的密钥
cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
return cookieRememberMeManager;
}
//创建 realm 对象
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
//配置ShiroDialect:方言,用于 thymeleaf 和 shiro 标签配合使用
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
UserRealm.java
package com.loey.config;
import com.loey.pojo.User;
import com.loey.service.UserService;
import org.apache.catalina.security.SecurityUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
//自定义Realm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
//执行授权逻辑
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("执行了=>授权逻辑PrincipalCollection");
//给资源授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加资源的授权字符串
/* info.addStringPermission("user:add");
info.addStringPermission("user:update");*/
//获得当前对象
Subject subject = SecurityUtils.getSubject();
//拿到user对象
User currentUser = (User) subject.getPrincipal();
//设置权限
info.addStringPermission(currentUser.getPerms());
return info;
}
//执行认证逻辑
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了=>认证逻辑AuthenticationToken");
//1.判断用户名
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
//真实连接数据库
User user = userService.queryUserByName(userToken.getUsername());
if(user == null){
//用户名不存在
return null;//shiro底层会抛出 UnknownAccountException
}
Subject subject = SecurityUtils.getSubject();
subject.getSession().setAttribute("loginUser",user);
//2. 验证密码,我们可以使用一个AuthenticationInfo实现类 SimpleAuthenticationInfo
// shiro会自动帮我们验证!重点是第二个参数就是要验证的密码
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
}
UserMapper.java
package com.loey.mapper;
import com.loey.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface UserMapper {
public User queryUserByName(@Param("userName") String userName);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace=绑定一个对应的mapper/Mapper接口-->
<mapper namespace="com.loey.mapper.UserMapper">
<select id="queryUserByName" resultType="User">
select * from user where username = #{userName};
</select>
</mapper>
MyController.java
//登录操作
@RequestMapping("/login")
public String login(String username,String password,String rememberMe,Model model){
//使用shiro编写认证操作
//1.获取Subject(当前用户)
Subject subject = SecurityUtils.getSubject();
//2.封装用户的数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
if("on".equals(rememberMe)){
token.setRememberMe(true);//调用Shiro记住我API方法
}else{
token.setRememberMe(false);
}
//3.执行登录的方法,只要没有异常就代表登录成功
try {
subject.login(token);
return "index";
}catch (UnknownAccountException uae) {//如果没有指定的用户,则 UnknownAccountException异常
model.addAttribute("msg","用户名不存在");
return "login";
} catch (IncorrectCredentialsException ice) {//密码不对的异常
model.addAttribute("msg","密码错误");
return "login";
}
}
页面视图