数据库结构
1. 项⽬⽬录结构
2. pom.xml 添加依赖
3. application.yml 配置⽂件
spring:
datasource:
url: jdbc:mysql://localhost:3306/tb_shiro?useUnicode=true&&characterEncoding=utf-8&serverTimezone=GMT username: root password: 123456
type: com.alibaba.druid.pool.DruidDataSource thymeleaf: cache: false
mybatis:
mapper-locations: classpath:mapping/*.xml type-aliases-package: cn.xej.pojo configuration:
map-underscore-to-camel-case: true # 该配置就是将带有下划线的表字段映射为驼峰格式的实体类属性
4. User 实体类
package cn.xej.pojo;import lombok.Data;@Data
public class User {
private String userId; private String password; private String name;}
5. UserDao接⼝
package cn.xej.mapper;
import cn.xej.pojo.User;
import org.springframework.stereotype.Repository;import java.util.List;@Repository
public interface UserDao {
public User findByUserId(String userId);
public List 6. UserDao.xml⽂件 PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\"> 7. UserService接⼝ package cn.xej.service;import cn.xej.pojo.User;import java.util.List; public interface UserService { // 根据⽤户id查询该⽤户 public User findByUserId(String userId); // 根据⽤户id获取该⽤户⾓⾊ public List 8. UserServiceimpl接⼝实现类 package cn.xej.service.impl; import cn.xej.mapper.UserDao;import cn.xej.pojo.User; import cn.xej.service.UserService; import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service; import java.util.List; @Service public class UserServiceimpl implements UserService { @Autowired private UserDao userDao; @Override public User findByUserId(String userId) { return userDao.findByUserId(userId); } @Override public List 9. SpringbootShiroApplication 启动类添加包扫描注解 package cn.xej; import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MapperScan(\"cn.xej.mapper\") // 配置⼀个或多个包路径,⾃动的扫描这些包路径下的类,⾃动的为它们⽣成代理类。public class SpringbootShiroApplication { public static void main(String[] args) { SpringApplication.run(SpringbootShiroApplication.class, args); }} 10. RespObj package cn.xej.common; import lombok.AllArgsConstructor;import lombok.Data; import lombok.NoArgsConstructor;@Data @AllArgsConstructor@NoArgsConstructorpublic class RespObj { private Integer code; private String message; private Object data; public static RespObj build(Integer code,String message,Object data){ return new RespObj(code,message,data); }} 11. SysController(路由跳转控制器) package cn.xej.controller; import org.apache.shiro.SecurityUtils;import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;@Controller public class SysController { // 进⼊到登录页⾯ @RequestMapping({\"/\ public String welcome(){ return \"login\"; } // 进⼊到⾸页(登录成功或游客) @RequestMapping(\"/index\") public String index(){ return \"index\"; } } 12. UserController(控制器) package cn.xej.controller; import cn.xej.common.RespObj;import cn.xej.pojo.User; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; 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.stereotype.Controller;import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpSession; @Controller @RequestMapping(\"/user\")public class UserController { // 登录⽤户, 返回json数据,因此要加 @ResponseBody注解 @PostMapping(\"/toLogin\") @ResponseBody public RespObj toLogin(String userId, String password, HttpSession session){ // 1. 获取 主体 subject Subject subject = SecurityUtils.getSubject(); // 2. 将账号和密码进⾏封装 UsernamePasswordToken token = new UsernamePasswordToken(userId,password); // 3. shiro认证,进⼊⾃定义UserRealm中 try { subject.login(token); // 认证成功,将⽤户名存到session中,返回json数据 session.setAttribute(\"currentUserName\ return RespObj.build(200,\"ok\null); } catch (Exception e) { System.out.println(\"账号或密码错误\"); return RespObj.build(500,\"账号或密码错误\null); } } // 注销⽤户 @PostMapping(\"/logout\") @ResponseBody public RespObj logout(){ Subject subject = SecurityUtils.getSubject(); subject.logout(); return RespObj.build(200,\"ok\null); } @RequestMapping(\"/add\") public String add(){ return \"pages/add\"; } @RequestMapping(\"/update\") public String update(){ return \"pages/update\"; }} 13. ⾃定义UserRealm package cn.xej.config; import cn.xej.pojo.User; import cn.xej.service.UserService;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.springframework.beans.factory.annotation.Autowired;import java.util.List; public class UserRealm extends AuthorizingRealm { @Autowired private UserService userService; // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println(\"授权\"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); User user = (User) principalCollection.getPrimaryPrincipal(); List // 认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println(\"认证\"); UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; User user = userService.findByUserId(token.getUsername()); if(user==null){ return null; } return new SimpleAuthenticationInfo(user,user.getPassword(),getName()); // 第⼀个参数,将会传到授权中进⾏获取,⽐如 User user = (User) principalCollection.getPrimaryPrincipal(); // 第⼆个参数,是该⽤户数据库⾥的密码 // 第三个参数,是当前类名 }} 14. Shiro配置⽂件(ShiroConfig) package cn.xej.config; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import java.util.LinkedHashMap;import java.util.Map; @Configuration // 该注解表⽰该类是 配置类public class ShiroConfig { // 我的所有⽅法名都是类名的⾸字母⼩写,不然要写成 @Bean(name=\"xxx\") xxx是⾃定义的⽅法名 // 配置⾃定义Realm @Bean public UserRealm userRealm(){ return new UserRealm(); } // 配置安全管理器,把⾃定义的Realm添加到安全管理器中 @Bean public DefaultWebSecurityManager defaultWebSecurityManager(UserRealm userRealm){ DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm(userRealm); return defaultWebSecurityManager; } // 配置Filter⼯⼚,设置对应的过滤条件和跳转条件,把安全管理器添加到Filter⼯⼚中 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); shiroFilterFactoryBean.setLoginUrl(\"/welcome\"); //设置进⼊登录页⾯的url shiroFilterFactoryBean.setUnauthorizedUrl(\"/unauthorized\"); shiroFilterFactoryBean.setSuccessUrl(\"/index\"); //设置登录成功url Map map.put(\"/index\ map.put(\"/user/toLogin\ map.put(\"/**\ shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } @Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); // 强制使⽤cglib,防⽌重复代理和可能引起代理出错的问题 defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor(); advisor.setSecurityManager(securityManager); return advisor; } @Bean public ShiroDialect shiroDialect(){ return new ShiroDialect(); }} 15. login.html页⾯ 16. index.html (⾸页) (当⽤户没登录时,三元表达式显⽰游客名字,登录时显⽰该⽤户名字,并通过shiro标签执⾏UserRealm中的授权⽅法,然后通过该⽤户的id获取他的⾓⾊) ⾸页 17. 实现⽤户密码加密 1. ⾸先在shiro 配置⽂件中 添加解密规则,如下⾯的解密凭证器,然后放到UserRealm中 // shiro 解密凭证器 @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName(\"MD5\"); hashedCredentialsMatcher.setHashIterations(1024); return hashedCredentialsMatcher; } // 配置⾃定义Realm @Bean public UserRealm userRealm(HashedCredentialsMatcher hashedCredentialsMatcher){ UserRealm userRealm = new UserRealm(); userRealm.setCredentialsMatcher(hashedCredentialsMatcher); return userRealm; } 2.然后在UserRealm 认证⽅法中,返回4个参数 // 认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println(\"认证\"); UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; User user = userService.findByUserId(token.getUsername()); if(user==null){ return null; } return new SimpleAuthenticationInfo(user,user.getPassword(), ByteSource.Util.bytes(user.getUserId()),getName()); // 第⼀个参数,将会传到授权中进⾏获取,⽐如 User user = (User) principalCollection.getPrimaryPrincipal(); // 第⼆个参数,是该⽤户数据库⾥的密码 // 第三个参数,是salt,这⾥我是⽤⽤户id当作盐 // 第四个参数,是当前类名 } 3. 最后写个测试⽅法,产⽣密码加密 “123” 是⽤户密码 “teacher1” 是加密的盐1024 是加密次数 String password1 = new SimpleHash(\"MD5\ System.out.println(\"password1 \"+password1); 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务