栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

使用springboot+shiro+mybatis+jwt+Redis完成前后端分离登录案例

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用springboot+shiro+mybatis+jwt+Redis完成前后端分离登录案例

 application配置

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://localhost:3306/companydb
    username: root
    password: 123456
  redis:
        database: 2
        host: localhost
        port: 6379
mybatis:
  mapper-locations: classpath*:mapper*Mapper.xml
xy:
  jwt:
    secret: xy@123 # 登录校验的密钥
    expire: 180 # 过期时间,单位分钟

添加依赖



	4.0.0
	
		org.springframework.boot
		spring-boot-starter-parent
		2.6.2
		
	
	com.itluma
	login0116
	0.0.1-SNAPSHOT
	login0116
	Demo project for Spring Boot
	
		1.8
	
	
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
		
			mysql
			mysql-connector-java
			5.1.36
		
		
		
			com.alibaba
			druid
			1.2.8
		

		
		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			1.3.2
		
		
		
			org.springframework
			spring-jdbc
			5.3.6
		
		
		
			org.apache.shiro
			shiro-spring
			1.4.1
		
		
		
			org.projectlombok
			lombok
			1.18.20
			provided
		
		
		
			com.alibaba
			fastjson
			1.2.28
		
		
			io.jsonwebtoken
			jjwt
			0.9.0
		
		
			joda-time
			joda-time
			2.10.4
		
		
			org.apache.commons
			commons-lang3
		
		
		
			org.springframework.boot
			spring-boot-starter-data-redis
		
	

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


实体类user

package com.itluma.login.entity;

import lombok.Data;

@Data
public class User {

    private Integer id;

    private String username;

    private String password;
}

shiro核心配置类

package com.itluma.login.config;

import com.itluma.login.filter.XyFormAuthenticationFilter;
import com.itluma.login.realm.XyRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.linkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Autowired
    private XyRealm realm;


    
    @Bean
    public DefaultWebSecurityManager defaultWebSecurityManager(){

        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(realm);
        return defaultWebSecurityManager;
    }


    
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){

        ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
        Map map = new linkedHashMap<>();
        //将自定义的过滤器添加到filterFactoryBean中
        Map filterMap = new linkedHashMap<>();
        filterMap.put("jwt",new XyFormAuthenticationFilter());
        filterFactoryBean.setFilters(filterMap);

        filterFactoryBean.setSecurityManager(defaultWebSecurityManager);

        //无需认证就可访问
        map.put("/user/login","anon");
        map.put("/user/captchaImage","anon");
        map.put("/","anon");
        map.put("*.html","anon");
        map.put("*.css","anon");
        map.put("*.js","anon");
        map.put("/profile
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(connectionFactory);

        ObjectMapper objectMapper = new ObjectMapper();
        //其实就是一个Jackson的转换器
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        objectMapper.activateDefaultTyping(LaissezFaireSubTypevalidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);


        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key采用String的序列化方式
        redisTemplate.setKeySerializer(RedisSerializer.string());
        // hash的key也采用String的序列化方式
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // value序列化方式采用jackson
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式采用jackson
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.afterPropertiesSet();

        return redisTemplate;
    }
}

controller

package com.itluma.login.controller;

import com.itluma.login.service.UserService;
import com.itluma.login.utils.JwtProperties;
import com.itluma.login.utils.RedisUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.cookie;
import javax.servlet.http.HttpServletResponse;

@RestController
@EnableConfigurationProperties(JwtProperties.class)
@RequestMapping("/user")
public class LoginController {

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisUtil redisUtil;

    @RequestMapping("/login")
    public String toLogin(String username,String password){

        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        Subject subject = SecurityUtils.getSubject();
        try{
            subject.login(token);
            //生成token
            String reToken = userService.generateToken(jwtProperties.getSecret(), jwtProperties.getExpire());
            redisUtil.set("token",reToken,3600);
            

            return "ok";
        }catch (Exception e){
            return "notok";
        }
    }

    @RequestMapping("/getInfo")
    public String getInfo(){

        return "yes";
    }

    @RequestMapping("/getInfo2")
    public String getInfo2(){

        return "yes2";
    }
}

mapper接口

package com.itluma.login.mapper;

import com.itluma.login.entity.User;

public interface UserMapper {

    
    User searchUserByUsername(String username);
}

service层接口

package com.itluma.login.service;

import com.itluma.login.entity.User;

public interface UserService {

    
    public User selectUser(String username);


    
    public String generateToken(String secret, Integer expireTime);
}

对应实现类

package com.itluma.login.service.impl;

import com.itluma.login.entity.User;
import com.itluma.login.mapper.UserMapper;
import com.itluma.login.service.UserService;
import com.itluma.login.utils.JwtUtils;
import com.itluma.login.vo.UserInfo;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class UserServiceImpl implements UserService{

    @Resource
    private UserMapper userMapper;

    
    @Override
    public User selectUser(String username) {

        User user = userMapper.searchUserByUsername(username);
        return user;
    }

    
    @Override
    public String generateToken(String secret, Integer expireTime) {

        User user = (User) SecurityUtils.getSubject().getPrincipal();
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId().longValue());
        userInfo.setUsername(user.getUsername());
        try {
            String token = JwtUtils.generateToken(userInfo, secret, expireTime);
            return token;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

自定义realm

package com.itluma.login.realm;

import com.itluma.login.entity.User;
import com.itluma.login.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Component
public class XyRealm extends AuthorizingRealm{

    @Autowired
    private UserService userService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {


        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        String username = token.getUsername();
        User user = userService.selectUser(username);
        if(user != null){
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),"XyRealm");
            return authenticationInfo;
        }
        return null;
    }
}

自定义过滤器filter

package com.itluma.login.filter;

import com.alibaba.fastjson.JSONObject;
import com.itluma.login.utils.JwtProperties;
import com.itluma.login.utils.RedisUtil;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class XyFormAuthenticationFilter extends FormAuthenticationFilter {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private JwtProperties jwtProperties;

    private static final Logger log = LoggerFactory.getLogger(FormAuthenticationFilter.class);

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

        System.out.println("过滤器执行啦");
        if (isLoginRequest(request, response)) {
            if (isLoginSubmission(request, response)) {
                if (log.isTraceEnabled()) {
                    log.trace("Login submission detected.  Attempting to execute login.");
                }
                return executeLogin(request, response);
            } else {
                if (log.isTraceEnabled()) {
                    log.trace("Login page view.");
                }
                //allow them to see the login page ;)
                return true;
            }
        } else {
            HttpServletRequest req = (HttpServletRequest)request;
            HttpServletResponse resp = (HttpServletResponse) response;
            if(req.getMethod().equals(RequestMethod.OPTIONS.name())) {
                resp.setStatus(HttpStatus.OK.value());
                return true;
            }

            if (log.isTraceEnabled()) {
                log.trace("Attempting to access a path which requires authentication.  Forwarding to the " +
                        "Authentication url [" + getLoginUrl() + "]");
            }
            //对token进行判断

            
            //前端Ajax请求时requestHeader里面带一些参数,用于判断是否是前端的请求
            resp.setHeader("Access-Control-Allow-Origin",  req.getHeader("Origin"));
                resp.setHeader("Access-Control-Allow-Credentials", "true");
                resp.setContentType("application/json; charset=utf-8");
                resp.setCharacterEncoding("UTF-8");
                PrintWriter out = resp.getWriter();
                JSonObject result = new JSonObject();
                result.put("message", "请登录!");
                result.put("statusCode", 401);
                out.println(result);
                out.flush();
                out.close();
            }
            return false;
        }
    }

.xml文件




    

到此,完结,散花~

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/711702.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号