实体类
@Data @AllArgsConstructor @NoArgsConstructor @TableName("t_user") public class RUser { @TableId(value="usr_id",type = IdType.AUTO) private Integer usrId; private String usrName; private String usrAccount; private String usrPassword; private String usrSalt; private String usrClazz; @TableField(exist = false) private Set<Role> roleSet; }
mapper
@Mapper public interface RUserMapper extends BaseMapper<RUser> { }
service
@Transactional public interface UserService { RUser queryByAccount(String account); }
service实现类
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private RUserMapper userMapper; @Override public RUser queryByAccount(String account) { QueryWrapper<RUser> userQueryWrapper = new QueryWrapper<>(); userQueryWrapper.eq("usr_account",account); RUser user = userMapper.selectOne(userQueryWrapper); return user; } }
首页
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> <meta charset="UTF-8"> <body> <h1>INDEX!!!</h1> <img src="../img/waji.jpg"> <shiro:notAuthenticated> <a href="/login">登录</a> </shiro:notAuthenticated> <shiro:authenticated><!--从会话中那,会话中是user对象--> welcome:<strong><shiro:principal property="usrName"/></strong> logining!! <a href="/logout">退出</a> </shiro:authenticated> </body> </html>
登录
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>登录</title> </head> <body> <article> <h1>登录</h1> <form action="login" method="post" > 账号:<input type="text" name="account" ><br> 密码:<input type="text" name="password"><br> <input type="submit" value="提交"><br> <span id="tip" style="color: red;" th:text="${tip}">默认值</span><br> </form> </article> </body> </html>
配置
application.yml
spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3307/shiro?useSSL=false&useUnicode=true&characterEncoding=UTF-8 username: root password: 123 logging: level: com.mapper: trace org.springframework.jdbc: trace # server: # port: 9999 # servlet: # context-path: /ssm mybatis-plus: type-aliases-package: com.entity
启动器
package com; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.realm.MyRealm; import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; import org.apache.shiro.mgt.DefaultSecurityManager; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import java.util.LinkedHashMap; import java.util.Map; @SpringBootApplication @MapperScan("com.mapper") public class SpringBoot02Application { public static void main(String[] args) { ApplicationContext ac = SpringApplication.run(SpringBoot02Application.class, args); System.out.println("访问:http://localhost:8080"); } /*添加分页插件*/ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } /* shiro相关配置*/ @Bean //密码匹配器 public SimpleCredentialsMatcher simpleCredentialsMatcher(){//简单的匹配规则,没有加密配置 SimpleCredentialsMatcher simpleCredentialsMatcher =new SimpleCredentialsMatcher(); return simpleCredentialsMatcher; } //会话管理器 @Bean public DefaultWebSessionManager defaultWebSessionManager(){ DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager(); return defaultWebSessionManager; } @Bean // 安全管理器 public DefaultWebSecurityManager defaultWebSecurityManager(SimpleCredentialsMatcher simpleCredentialsMatcher, MyRealm realm, DefaultWebSessionManager defaultWebSessionManager) { DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); realm.setCredentialsMatcher(simpleCredentialsMatcher); defaultWebSecurityManager.setRealm(realm); defaultWebSecurityManager.setSessionManager(defaultWebSessionManager); return defaultWebSecurityManager; } //过滤法则 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>(); //有顺序 不用无序的HashMap //放行 //静态资源放行 filterChainDefinitionMap.put("/favicon.ico","anon"); filterChainDefinitionMap.put("/css/**","anon"); filterChainDefinitionMap.put("/js/**","anon"); filterChainDefinitionMap.put("/img/**","anon"); //动态资源放行 filterChainDefinitionMap.put("/","anon"); filterChainDefinitionMap.put("/a","anon"); filterChainDefinitionMap.put("/login","anon"); filterChainDefinitionMap.put("/logout","logout"); //不放行 filterChainDefinitionMap.put("/**","authc"); //未认证跳往地址 shiroFilterFactoryBean.setLoginUrl("/"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } //方言 @Bean public ShiroDialect shiroDialect(){ ShiroDialect shiroDialect=new ShiroDialect(); return shiroDialect; } }
pom.xml
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <!--mysql5以及之前使用的是:com.mysql.jdbc. Driver mysql6以及之后使用的是: com.mysql.cj.jdbc.Driver 若配置文件爆红则把版本去掉,或先把标签换成compile,再换回来runtime --> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--shiro--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-starter</artifactId> <version>1.8.0</version> </dependency> <!--方言--> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.1.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
UserController
package com.controller; import com.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; 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.context.annotation.Lazy; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Controller public class UserController { @GetMapping("/login") public String login(){ return "login"; } @PostMapping("/login") public String login(String account, String password, Model model){ Subject subject = SecurityUtils.getSubject(); try { subject.login(new UsernamePasswordToken(account,password)); return "redirect:/"; }catch (UnknownAccountException e){ model.addAttribute("tip","账号不存在"); return "login"; }catch (AuthenticationException e){ model.addAttribute("tip","账号或密码错误"); return "login"; } } }
首页:
失败:
成功: