您好,欢迎来到年旅网。
搜索
您的当前位置:首页springboot整合shiro(使用了thymeleaf模板引擎)

springboot整合shiro(使用了thymeleaf模板引擎)

来源:年旅网
springboot整合shiro(使⽤了thymeleaf模板引擎)

数据库结构

1. 项⽬⽬录结构

2. pom.xml 添加依赖

4.0.0

org.springframework.boot spring-boot-starter-parent 2.2.2.RELEASE

cn.xej

springboot-shiro 0.0.1-SNAPSHOT springboot-shiro

Demo project for Spring Boot

1.8

org.springframework.boot spring-boot-starter-web

org.mybatis.spring.boot

mybatis-spring-boot-starter 2.1.2

mysql

mysql-connector-java

org.apache.shiro shiro-spring 1.4.1

com.github.theborakompanioni thymeleaf-extras-shiro 2.0.0

org.springframework.boot

spring-boot-starter-thymeleaf

org.springframework.boot spring-boot-devtools runtime true

com.alibaba druid 1.1.13

org.projectlombok lombok true

org.springframework.boot spring-boot-starter-test test

org.junit.vintage

junit-vintage-engine

org.springframework.boot spring-boot-maven-plugin

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 queryRolesIdByUserId(String userId);}

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 getRolesIdByUserId(String userId);}

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 getRolesIdByUserId(String userId) { return userDao.queryRolesIdByUserId(userId); }}

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 roles = userService.getRolesIdByUserId(user.getUserId()); info.addRoles(roles); return info; }

// 认证 @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 = new LinkedHashMap();     // index和 user/toLogin两个路径不⽤拦截

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页⾯

Title

账号

密码

16. index.html (⾸页) (当⽤户没登录时,三元表达式显⽰游客名字,登录时显⽰该⽤户名字,并通过shiro标签执⾏UserRealm中的授权⽅法,然后通过该⽤户的id获取他的⾓⾊)

Title

⾸页



登录

注销

添加教师
更新教师

添加学⽣
更新学⽣

普通学⽣

游客

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

本站由北京市万商天勤律师事务所王兴未律师提供法律服务