下面写个简单的token单一点登录系统来验证下。当访问系统未登录时,跳转到登录页,登录后进入首页,左侧导航栏展示默认菜单(首页)和有权限的菜单。
一、写在前面:关于session和token的使用,网上争议一直很大。总的来说争议在这里:
(1)session是空间换时间,而token是时间换空间。session占用空间,但是可以管理过期时间,token管理部了过期时间,但是不占用空间.
(2)sessionId失效问题和token内包含。
(3)session基于cookie,app请求并没有cookie 。
(4)token更加安全(每次请求都需要带上)。
二、效果:
前端:vue;
后端:springboot+dubbo+mybatis+spring sercurity+JWT+ token单一点登录。
效果:
分别启动前后端服务,访问首页http://localhost:9528/#/index,由于未登录,跳转到登录页
登录后跳转到首页,http://localhost:9528/#/dashboard
左侧菜单栏展开,显示所有的权限:
此时在postman调用一次登录接口,再次回到浏览器刷新或者调用接口(如点击用户管理页),跳转到登录页面。证明单一点登录实现。
三、数据库:
1、t_user:
2、t_role:
3、t_authority:
4、t_user_role:
5、t_role_authoriy:
四、后端代码:
- api:
1、pom:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>mysercurity-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</project>
2、dto:
public class AuthorityDTO implements Serializable {
private Integer id;
private String authorityName;
private String authorityCode;
}
public class RoleDTO implements Serializable {
private Integer id;
private String roleCode;
private String roleName;
}
public class UserDTO implements Serializable {
private Integer id;
private String userName;
private String password;
private String userNickName;
//验证码
private String code;
private List<RoleDTO> roles;
}
- service:
1、pom:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>mysercurity-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- springBoot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- api -->
<dependency>
<groupId>com.demo</groupId>
<artifactId>mysercurity-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
</dependency>
<!--zk-->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
2、application.properties:
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=wtyy
mybatis.mapper-locations=classpath*:Mapper/*Mapper.xml
server.port=9998
3、provider.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="mysercurity-service"/>
<dubbo:provider timeout="3000" retries="0"/>
<!-- register改为false不注册到注册中心 -->
<dubbo:registry protocol="zookeeper" address="192.168.57.xxx:2181,192.168.57.xx:2181,192.168.59.xxx:2181"
register="false" check="false"/>
<dubbo:protocol name="dubbo" port="20881"/>
<dubbo:service interface="com.demo.service.UserService" ref="userService"></dubbo:service>
<dubbo:service interface="com.demo.service.RoleService" ref="roleService"></dubbo:service>
</beans>
4、serviceImpl:
package com.demo.service.impl;
import com.demo.dao.UserRoleDao;
import com.demo.dto.RoleDTO;
import com.demo.service.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("roleService")
public class RoleServiceImpl implements RoleService {
@Autowired
private UserRoleDao userRoleDao;
@Override
public List<RoleDTO> findRoleByUserId(Integer id) {
return userRoleDao.findRoleByUserId(id);
}
}
package com.demo.service.impl;
import com.demo.dao.AuthorityDao;
import com.demo.dao.UserDao;
import com.demo.dao.UserRoleDao;
import com.demo.dto.AuthorityDTO;
import com.demo.dto.RoleDTO;
import com.demo.dto.UserDTO;
import com.demo.exception.UsernameNotFoundException;
import com.demo.service.RoleService;
import com.demo.service.UserService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Autowired
private UserRoleDao userRoleDao;
@Autowired
private AuthorityDao authorityDao;
@Autowired
private RoleService roleService;
@Override
public UserDTO findByUserName(String username) {
UserDTO user = userDao.findByUserName(username);
if(user == null){
throw new UsernameNotFoundException("用户不存在");
}
List<RoleDTO> roles = roleService.findRoleByUserId(user.getId());
user.setRoles(roles);
return user;
}
@Override
public List<UserDTO> getAllUsers() {
return userDao.getAllUsers();
}
@Override
public List<AuthorityDTO> getAuthortiesByUserId(Integer userId) {
List<RoleDTO> roles = userRoleDao.findRoleByUserId(userId);
if(CollectionUtils.isNotEmpty(roles)){
List<Integer> roleIds = roles.stream().map(RoleDTO::getId).collect(Collectors.toList());
return authorityDao.getAuthortiesByRoleIds(roleIds);
}
return new ArrayList<>();
}
}
5、dao:
public interface AuthorityDao {
List<AuthorityDTO> getAuthortiesByRoleIds(@Param("roleIds") List<Integer> roleIds);
}
<?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">
<mapper namespace="com.demo.dao.AuthorityDao">
<select id="getAuthortiesByRoleIds" resultType="com.demo.dto.AuthorityDTO">
select
a.id id,
a.authority_code authorityCode,
a.authority_name authorityName
from t_role_authoriy ra left join t_authority a on ra.authority_id = a.id
where ra.role_id in
<foreach collection="roleIds" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
and ra.is_delete = 0
</select>
</mapper>
public interface UserDao {
public UserDTO findByUserName(@Param("userName") String userAccount);
List<UserDTO> getAllUsers();
}
<?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">
<mapper namespace="com.demo.dao.UserDao">
<select id="findByUserName" resultType="com.demo.dto.UserDTO">
select
id,
user_nick_name userNickName,
user_name userName,
user_nick_name userNickName,
user_password password
from t_user where user_name = #{userName}
and is_delete = 0
</select>
<select id="getAllUsers" resultType="com.demo.dto.UserDTO">
select
id,
user_nick_name userNickName,
user_name userName,
user_nick_name userNickName
from t_user
</select>
</mapper>
public interface UserRoleDao {
List<RoleDTO> findRoleByUserId(@Param("userId") Integer userId);
}
<?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">
<mapper namespace="com.demo.dao.UserRoleDao">
<select id="findRoleByUserId" resultType="com.demo.dto.RoleDTO">
select
r.id id,
r.role_code roleCode,
r.role_name roleName
from t_user_role ur
left join t_role r
on ur.role_id = r.id
where ur.user_id = #{userId}
and is_delete = 0
</select>
</mapper>
6、启动类:
package com.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@MapperScan("com.demo.dao")
@ImportResource("classpath:provider.xml")
public class ServiceStart {
public static void main(String args[]){
SpringApplication.run(ServiceStart.class,args);
}
}
- rest:
1、pom:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>mysercurity-rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies>
<!--api-->
<dependency>
<groupId>com.demo</groupId>
<artifactId>mysercurity-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>com.alibaba.spring.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!--httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.6</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
</dependency>
<!--zk-->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
2、配置文件:
(1)application.properties:
server.port=9999
server.context-path=/demo
spring.redis.host=localhost
spring.redis.port=6379
#spring.redis.password=
spring.redis.database=1
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=500
spring.redis.pool.min-idle=0
spring.redis.timeout=0
(2) consumer.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<dubbo:application name="mysercurity-test" />
<dubbo:consumer timeout="3000" retries="0" check="false"/>
<dubbo:registry protocol="zookeeper" address="192.168.57.xxx:2181,192.168.57.xx:2181,192.168.59.xxx:2181" register="true" timeout="100000"/>
<!-- 加上 url="dubbo://127.0.0.1:20881" 表示直连本地-->
<dubbo:reference interface="com.demo.service.UserService" id="userService"
url="dubbo://127.0.0.1:20881"/>
<dubbo:reference interface="com.demo.service.RoleService" id="roleService"
url="dubbo://127.0.0.1:20881"/>
</beans>
3、config:
package com.demo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("*")
.allowCredentials(true);
}
}
4、常量:
(1)CommonEnums:
package com.demo.constants;
public enum CommonEnums {
CODE_200(200,"请求成功"),
CODE_300(300,"登录成功"),
CODE_301(301,"登录失败"),
CODE_302(302,"退出成功"),
CODE_303(303,"退出失败"),
CODE_304(304,"用户或密码错误"),
CODE_305(305,"账户已被锁定"),
CODE_401(401,"授权失败"),
CODE_400(400,"业务异常"),
CODE_402(402,"非法请求"),
CODE_403(403,"验证码错误"),
CODE_405(405,"验证码无效"),
CODE_500(500,"系统异常"),
;
public final int code;
public final String message;
CommonEnums(int code, String message ) {
this.code = code;
this.message = message;
}
public int getCode() {
return this.code;
}
public String getMessage() {
return message;
}
public static String getEnumToValue(int code){
for (CommonEnums statusEnum: CommonEnums.values()) {
if (statusEnum.code == code){
return statusEnum.message;
}
}
return "";
}
}
(2)Constants :
package com.demo.constants;
public class Constants {
public static final long EXPIRATIONTIME = (long)1000 * 60 * 60 * 24 * 1; //1 days
public static final String SECRET = "spring-security-jwt";
public static final String HEADER_STRING = "token";
public static final String TOKEN_PREFIX = "Bearer";
public static final String TOKEN_JWT="token_jwt:";
public static final String JWT_USER="jwt_user:";
public static final String LOCK="lock:";
public static final String ERROR_NUM="error_num:";
}
5、dto:
(1)JWTUserDTO:
package com.demo.dto;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* 登录用户
*/
public class JWTUserDTO implements UserDetails {
private Integer id;
private String userName;
private String password;
private String userNickName;
private List<RoleDTO> roles = new ArrayList<>();
private Collection<? extends GrantedAuthority> authorities;
public JWTUserDTO(){
}
public JWTUserDTO(Integer id, String userName, String password, String userNickName,
Collection<? extends GrantedAuthority> authorities, List<RoleDTO> roles){
this.id = id;
this.userName = userName;
this.userNickName = userNickName;
this.password = password;
this.authorities = authorities;
this.roles = roles;
}
@Override
public String getUsername() {
return userName;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
public void setUsername(String username) {
this.userName = username;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void setPassword(String password) {
this.password = password;
}
public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
this.authorities = authorities;
}
public List<RoleDTO> getRoles() {
return roles;
}
public void setRoles(List<RoleDTO> roles) {
this.roles = roles;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserNickName() {
return userNickName;
}
public void setUserNickName(String userNickName) {
this.userNickName = userNickName;
}
}
(2)ResponseMessage:
package com.demo.dto;
import com.demo.constants.CommonEnums;
public class ResponseMessage {
private int code;
private String status;
private String message;
private String errorMessage;
private String errorExceptionMessage;
private Object data;
public ResponseMessage(int code,String status,Object data){
this.code = code;
this.status = status;
this.data = data;
}
public ResponseMessage(int code,String status,String message){
this.code = code;
this.status = status;
this.message = message;
}
public ResponseMessage(int code,String status,String message,Object data){
this.code = code;
this.status = status;
this.message = message;
this.data = data;
}
public ResponseMessage(int code,String status,String message,String errorMessage){
this.code = code;
this.status = status;
this.message = message;
this.errorMessage = errorMessage;
}
public ResponseMessage(int code,String status,String message,String errorMessage,String errorExceptionMessage){
this.code = code;
this.status = status;
this.message = message;
this.errorMessage = errorMessage;
this.errorExceptionMessage = errorExceptionMessage;
}
public static ResponseMessage success(String message){
return new ResponseMessage(CommonEnums.CODE_200.code,"success",message);
}
public static ResponseMessage success(Object data){
return new ResponseMessage(CommonEnums.CODE_200.code,"success",data);
}
public static ResponseMessage success(String message,Object data){
return new ResponseMessage(CommonEnums.CODE_200.code,"success",message,data);
}
public static ResponseMessage success(int code,String message,Object data){
return new ResponseMessage(code,"success",message,data);
}
public static ResponseMessage success(){
return new ResponseMessage(CommonEnums.CODE_200.code,null,CommonEnums.CODE_200.message);
}
public static ResponseMessage success(int code,Object data){
return new ResponseMessage(code,"success",data);
}
public static ResponseMessage success(int code,String message){
return new ResponseMessage(code,"success",message);
}
public static ResponseMessage error(int code,String message){
return new ResponseMessage(code,"error",message);
}
public static ResponseMessage error(int code,String message,String errorMessage){
return new ResponseMessage(code,"error",message,errorMessage);
}
public static ResponseMessage error(int code,String message,String errorMessage,String errorExceptionMessage){
return new ResponseMessage(code,"error",message,errorMessage,errorExceptionMessage);
}
public static ResponseMessage error(String message,String errorMessage){
return new ResponseMessage(CommonEnums.CODE_500.code,"error",message,errorMessage);
}
public static ResponseMessage error(String message){
return new ResponseMessage(CommonEnums.CODE_400.code,"error",message);
}
public static ResponseMessage infor(int code,String message){
return new ResponseMessage(code,"infor",message);
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getErrorExceptionMessage() {
return errorExceptionMessage;
}
public void setErrorExceptionMessage(String errorExceptionMessage) {
this.errorExceptionMessage = errorExceptionMessage;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
6、exception:
(1):
package com.demo.exception;
import com.alibaba.fastjson.JSON;
import com.demo.constants.CommonEnums;
import com.demo.dto.ResponseMessage;
import org.apache.http.entity.ContentType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse, AuthenticationException e)
throws IOException, ServletException {
httpServletResponse.setContentType(ContentType.APPLICATION_JSON.toString());
httpServletResponse.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_304.code,CommonEnums.CODE_304.message)));
}
}
(2):
package com.demo.exception;
import com.alibaba.fastjson.JSON;
import com.demo.constants.CommonEnums;
import com.demo.dto.ResponseMessage;
import org.apache.http.entity.ContentType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Http401AuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.setContentType(ContentType.APPLICATION_JSON.toString());
response.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_401.code,CommonEnums.CODE_401.message)));
}
}
(3):
package com.demo.exception;
public class TokenException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TokenException(String message) {
super(message);
}
}
7、factory:主要是全局上下文:
(1):
package com.demo.factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class ApplicationContextRegister implements ApplicationContextAware {
private static Logger logger = LoggerFactory.getLogger(ApplicationContextRegister.class);
private static ApplicationContext APPLICATION_CONTEXT;
/**
* 设置spring上下文
* @param applicationContext spring上下文
* @throws BeansException
* */
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
logger.debug("ApplicationContext registed-->{}", applicationContext);
DefaultBeanFactory.setSpringApplicationContext(applicationContext);
APPLICATION_CONTEXT = applicationContext;
}
/**
* 获取容器
* @return
*/
public static ApplicationContext getApplicationContext() {
return APPLICATION_CONTEXT;
}
/**
* 获取容器对象
* @param type
* @param <T>
* @return
*/
public static <T> T getBean(Class<T> type) {
return APPLICATION_CONTEXT.getBean(type);
}
}
(2):
package com.demo.factory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DefaultBeanFactory {
private static ApplicationContext context = null;
private static DefaultBeanFactory instance = null;
private static Object lock = new Object();
private DefaultBeanFactory(String filepath){
try {
context = new ClassPathXmlApplicationContext(filepath);
} catch (Exception e) {
}
}
@SuppressWarnings("static-access")
private DefaultBeanFactory(ApplicationContext context){
try {
this.context = context;
} catch (Exception e) {
}
}
public static void setSpringApplicationContext(ApplicationContext context){
synchronized (lock) {
instance = new DefaultBeanFactory(context);
}
}
public static DefaultBeanFactory getInstance() {
if(instance == null || context == null){
throw new RuntimeException("Spring context is null!");
}
return instance;
}
public static DefaultBeanFactory getInstance(String filepath) {
synchronized (lock) {
instance = new DefaultBeanFactory(filepath);
}
return instance;
}
public Object getBean(String name) {
return context.getBean(name);
}
}
(3):
package com.demo.factory;
import com.demo.util.RedisClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ServiceFactory {
private static Logger logger = LoggerFactory.getLogger(ServiceFactory.class);
private static ServiceFactory instance = new ServiceFactory();
private final String REDIS_CLIENT_BEAN="redisClient";
private final String USER_ACTION_LOG_SERVICE = "userActionLogService";
public ServiceFactory() {
// TODO Auto-generated constructor stub
}
public static ServiceFactory getInstance() {
if (instance == null) {
instance = new ServiceFactory();
}
return instance;
}
public RedisClient createRedisClient() {
try {
return (RedisClient) DefaultBeanFactory.getInstance().getBean(REDIS_CLIENT_BEAN);
} catch (Exception e) {
throw new RuntimeException("创建 createRedisClient BEAN 异常", e);
}
}
}
8、filter:
(1):
package com.demo.filter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.demo.constants.CommonEnums;
import com.demo.constants.Constants;
import com.demo.dto.JWTUserDTO;
import com.demo.dto.ResponseMessage;
import com.demo.dto.UserDTO;
import com.demo.factory.ServiceFactory;
import com.demo.service.UserService;
import com.demo.util.JwtProvider;
import com.demo.util.RedisClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
import org.apache.http.entity.ContentType;
/**非登录接口拦截
*
* 自定义JWT认证过滤器
* 该类继承自BasicAuthenticationFilter,在doFilterInternal方法中,
* 从http头的Authorization 项读取token数据,然后用Jwts包提供的方法校验token的合法性。
* 如果校验通过,就认为这是一个取得授权的合法请求
*/
public class JWTAuthenticationFilter extends BasicAuthenticationFilter{
private static final Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
private static RedisClient redisClient;
static {
redisClient = ServiceFactory.getInstance().createRedisClient();
}
private UserService userService;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager,
UserService userService) {
super(authenticationManager);
this.userService = userService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String token = request.getHeader(Constants.HEADER_STRING);
String username = JwtProvider.getAuthentication(request);
if(StringUtils.isEmpty(username)){
response.sendError(HttpStatus.UNAUTHORIZED.value(), "Authentication Failed: username not found");
return;
}
//效验token是否过期
String tokenReids = redisClient.get(Constants.TOKEN_JWT+username);
if (StringUtils.isEmpty(tokenReids)){
logger.error("Token已过期: {} ",token);
response.setContentType(ContentType.APPLICATION_JSON.toString());
response.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_401.code,"Token已过期")));
return;
}
if (!Objects.equals(tokenReids,token)){
logger.error("Token不匹配: {} " + tokenReids);
response.setContentType(ContentType.APPLICATION_JSON.toString());
response.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_401.code,"Token不匹配")));
return;
}
// if(SecurityContextHolder.getContext().getAuthentication() == null) {
String userJson = redisClient.get(Constants.JWT_USER+username);
UserDetails userDetails = null;
if (!StringUtils.isEmpty(userJson)){
JWTUserDTO jwtUser = JSONObject.parseObject(userJson,JWTUserDTO.class);
userDetails = jwtUser;
}else{
UserDTO user = userService.findByUserName(username);
userDetails = new JWTUserDTO(user.getId(),user.getUserName(),user.getPassword(),
user.getUserNickName(),null,user.getRoles());
redisClient.set(Constants.JWT_USER+username, JSONObject.toJSONString(userDetails));
}
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
// }
chain.doFilter(request, response);
}
}
(2):
package com.demo.filter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.demo.constants.CommonEnums;
import com.demo.constants.Constants;
import com.demo.dto.JWTUserDTO;
import com.demo.dto.ResponseMessage;
import com.demo.dto.UserDTO;
import com.demo.exception.CustomAuthenticationFailureHandler;
import com.demo.factory.ServiceFactory;
import com.demo.service.UserService;
import com.demo.util.JwtProvider;
import com.demo.util.RedisClient;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Objects;
/**登录接口(/login)拦截
*
* 验证用户名密码正确后,生成一个token,并将token返回给客户端
* 该类继承自UsernamePasswordAuthenticationFilter,重写了其中的2个方法
* attemptAuthentication :接收并解析用户凭证。
* successfulAuthentication :用户成功登录后,这个方法会被调用,我们在这个方法里生成token。
*/
public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter{
private static Logger logger = LoggerFactory.getLogger(JWTLoginFilter.class);
private AuthenticationManager authenticationManager;
private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
private UserService userService;
private static RedisClient redisClient;
static {
redisClient = ServiceFactory.getInstance().createRedisClient();
}
public JWTLoginFilter(AuthenticationManager authenticationManager,
CustomAuthenticationFailureHandler customAuthenticationFailureHandler,
UserService userService) {
this.authenticationManager = authenticationManager;
this.customAuthenticationFailureHandler = customAuthenticationFailureHandler;
this.userService = userService;
setAuthenticationManager(authenticationManager);
}
// 接收并解析用户凭证
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException {
String userName = "";
HttpSession httpSession = req.getSession();
try {
UserDTO user = new ObjectMapper().readValue(req.getInputStream(), UserDTO.class);
//判断用户是否多次登录失败被锁定
String lock = redisClient.get(Constants.LOCK+user.getUserName());
if (StringUtils.isNotEmpty(lock)) {
httpSession.setAttribute("code",null);
Long time = redisClient.ttl(Constants.LOCK+user.getUserName());
res.setContentType(ContentType.APPLICATION_JSON.toString());
res.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_305.code, CommonEnums.CODE_305.message+":"+time+"秒后解锁")));
return null;
}
//校验验证码
if (StringUtils.isNotEmpty(user.getCode())){
if (!Objects.equals(user.getCode(),"1111")){
String code = (String) httpSession.getAttribute("code");
if(StringUtils.isEmpty(code)){
httpSession.setAttribute("code",null);
res.setContentType(ContentType.APPLICATION_JSON.toString());
res.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_405.code,CommonEnums.CODE_405.message)));
return null;
}
if (!Objects.equals(user.getCode().toLowerCase(),code.toLowerCase())){
httpSession.setAttribute("code",null);
res.setContentType(ContentType.APPLICATION_JSON.toString());
res.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_403.code,CommonEnums.CODE_403.message)));
return null;
}
}
}else{
httpSession.setAttribute("code",null);
res.setContentType(ContentType.APPLICATION_JSON.toString());
res.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_405.code,CommonEnums.CODE_405.message)));
}
userName = user.getUserName();
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
user.getUserName(),
user.getPassword(),
new ArrayList<>())
);
}catch (IOException e) {
throw new RuntimeException(e);
}catch (UsernameNotFoundException | BadCredentialsException e){
try {
if (StringUtils.isNotEmpty(userName)){
String errorNum = redisClient.get(Constants.ERROR_NUM+userName);
if (StringUtils.isNotEmpty(errorNum)){
if (Objects.equals(errorNum,"3")){
httpSession.setAttribute("code",null);
redisClient.set(Constants.LOCK+userName,"true",120);
res.setContentType(ContentType.APPLICATION_JSON.toString());
res.getWriter().write(JSON.toJSONString(ResponseMessage.error(CommonEnums.CODE_305.code,CommonEnums.CODE_305.message+":120秒后解锁")));
}else{
httpSession.setAttribute("code",null);
redisClient.set(Constants.ERROR_NUM+userName,String.valueOf(Integer.valueOf(errorNum)+1),120);
customAuthenticationFailureHandler.onAuthenticationFailure(req,res,e);
}
}else{
httpSession.setAttribute("code",null);
redisClient.set(Constants.ERROR_NUM+userName,"1",120);
customAuthenticationFailureHandler.onAuthenticationFailure(req,res,e);
}
}else{
httpSession.setAttribute("code",null);
customAuthenticationFailureHandler.onAuthenticationFailure(req,res,e);
}
} catch (Exception e1) {
throw new RuntimeException(e);
}
return null;
}
}
// 用户成功登录后,这个方法会被调用,我们在这个方法里生成token
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication auth) throws IOException, ServletException {
HttpSession httpSession = request.getSession();
httpSession.setAttribute("code",null);
redisClient.del(Constants.LOCK+auth.getName());
redisClient.del(Constants.ERROR_NUM+auth.getName());
String token = JwtProvider.addAuthentication(response, auth.getName());
UserDTO userDTO = userService.findByUserName(auth.getName());
JWTUserDTO userDetails = new JWTUserDTO(userDTO.getId(),userDTO.getUserName(),userDTO.getPassword(),
userDTO.getUserNickName(),null,userDTO.getRoles());;
redisClient.set(Constants.JWT_USER+auth.getName(), JSONObject.toJSONString(userDetails));
response.setContentType(ContentType.APPLICATION_JSON.toString());
response.getWriter().write(JSON.toJSONString(ResponseMessage.success(CommonEnums.CODE_300.code,CommonEnums.CODE_300.message,token)));
}
}
9、rest接口:
(1) :
package com.demo.rest;
import com.demo.dto.ResponseMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Random;
@RestController
@RequestMapping("/code")
public class CodeController {
private static Logger logger = LoggerFactory.getLogger(CodeController.class);
/**
* 获取验证码
*/
@GetMapping(value = "/getCode")
public ResponseMessage images(HttpServletRequest request, HttpServletResponse response) {
try {
HttpSession httpSession = request.getSession();
Random r = new Random();
String code = String.valueOf(r.nextInt(100));
httpSession.setAttribute("code",code);
return ResponseMessage.success("验证码",code);
} catch (Exception e) {
logger.error("ValidateCodeController images ERROR MESSAGE={}", e.getMessage(), e);
}
return ResponseMessage.error("");
}
}
(2):
package com.demo.rest;
import com.demo.constants.CommonEnums;
import com.demo.constants.Constants;
import com.demo.dto.AuthorityDTO;
import com.demo.dto.JWTUserDTO;
import com.demo.dto.ResponseMessage;
import com.demo.dto.UserDTO;
import com.demo.service.UserService;
import com.demo.util.RedisClient;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private UserService userService;
@Autowired
private RedisClient redisClient;
/**
* 获取所有用户
* @return
*/
@RequestMapping("/getAllUsers")
public ResponseMessage getAllUsers(){
List<UserDTO> users = userService.getAllUsers();
return ResponseMessage.success(users);
}
/**
* 获取权限
*/
@RequestMapping("/getMyAuthorities")
public ResponseMessage getMyAuthorities(){
JWTUserDTO jwtUser = (JWTUserDTO) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Integer currentUserId = jwtUser.getId();
List<AuthorityDTO> authorityDTOS= userService.getAuthortiesByUserId(currentUserId);
return ResponseMessage.success(authorityDTOS);
}
@GetMapping(value = "/logout")
public ResponseMessage logout(HttpServletRequest request) {
try{
JWTUserDTO jwtUser = (JWTUserDTO)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String userName = jwtUser.getUsername();
if (StringUtils.isEmpty(userName)){
throw new RuntimeException(CommonEnums.CODE_303.message);
}
redisClient.del(Constants.TOKEN_JWT+userName);
request.logout();
}catch (Exception e){
}
return ResponseMessage.success(CommonEnums.CODE_200.code,CommonEnums.CODE_200.message);
}
}
10、sercurity:
package com.demo.sercurity;
import com.demo.exception.CustomAuthenticationFailureHandler;
import com.demo.exception.Http401AuthenticationEntryPoint;
import com.demo.filter.JWTAuthenticationFilter;
import com.demo.filter.JWTLoginFilter;
import com.demo.service.CustomAuthenticationProvider;
import com.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* SpringSecurity的配置
* 通过SpringSecurity的配置,将JWTLoginFilter,JWTAuthenticationFilter组合在一起
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**白名单
* 需要放行的URL
*/
private static final String[] AUTH_WHITELIST = {
"/v2/api-docs",
"/swagger-resources",
"/swagger-resources/**",
"/configuration/ui",
"/configuration/security",
"/swagger-ui.html",
"/static",
"/static/diagram-viewer",
"/static/**",
"/index.html",
"/code/**", //验证码
};
@Autowired
private UserService userService;
@Autowired
private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
// 设置 HTTP 验证规则
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.anyRequest().authenticated() // 所有请求需要身份认证
.and()
.exceptionHandling()
.authenticationEntryPoint(
new Http401AuthenticationEntryPoint())
.and()
.addFilterBefore(new JWTLoginFilter(authenticationManager(),customAuthenticationFailureHandler,userService), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(authenticationManager(),userService), UsernamePasswordAuthenticationFilter.class);
//因为是spring整合了spring Security,本例加了session共享,每次检查原session的时候如果不存在的话,就会创建新的session,故需要手动设置
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
}
// 该方法是登录的时候会进入
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
// 使用自定义身份验证组件
auth.authenticationProvider(new CustomAuthenticationProvider(userService));
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(AUTH_WHITELIST);
}
}
11、 service:
package com.demo.service;
import com.demo.dto.JWTUserDTO;
import com.demo.dto.UserDTO;
import com.demo.util.AESUtils;
import com.demo.util.MD5Util;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
/**
* 自定义身份认证验证组件
*/
public class CustomAuthenticationProvider implements AuthenticationProvider {
private UserService userService;
public CustomAuthenticationProvider(
UserService userService
){
this.userService = userService;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 获取认证的用户名 & 密码
//前端带入的username
String username = authentication.getName();
//前端带入的加密password
String passwordRsa = authentication.getCredentials().toString();
//passwordRsa解密后的密码
String password = "";
String passwordMd5 = "";
//RSA解密
try {
password = AESUtils.decryptStr(passwordRsa,AESUtils.key);
} catch (Exception e) {
throw new UsernameNotFoundException("用户不存在");
}
UserDTO userDO = userService.findByUserName(username);
if (userDO == null) {
throw new UsernameNotFoundException("用户不存在");
}
//判断密码
try {
//md5加密
passwordMd5 = MD5Util.MD5(password);
} catch (NoSuchAlgorithmException e) {
throw new UsernameNotFoundException("用户不存在");
}
if (!Objects.equals(passwordMd5,userDO.getPassword())){
throw new BadCredentialsException("密码错误");
}
UserDTO userDTO = userService.findByUserName(username);
JWTUserDTO userDetails = new JWTUserDTO(userDTO.getId(),userDTO.getUserName(),userDTO.getPassword(),
userDTO.getUserNickName(),null,userDTO.getRoles());
// 这里设置权限和角色
Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null,userDetails.getAuthorities());
return auth;
}
/**
* 是否可以提供输入类型的认证服务
* @param authentication
* @return
*/
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
12、util:
(1):
package com.demo.util;
import javax.crypto.*;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class AESUtils {
private static String iv = "HGty&6%4ojyUyhgy";//偏移量字符串必须是16位 当模式是CBC的时候必须设置偏移量
private static String Algorithm = "AES";
private static String AlgorithmProvider = "AES/CBC/PKCS5Padding"; //算法/模式/补码方式
public final static String key="FUjs@17654HGJKKn";
public static byte[] generatorKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(Algorithm);
keyGenerator.init(256);//默认128,获得无政策权限后可为192或256
SecretKey secretKey = keyGenerator.generateKey();
return secretKey.getEncoded();
}
public static IvParameterSpec getIv() throws UnsupportedEncodingException {
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes("utf-8"));
System.out.println("偏移量:"+byteToHexString(ivParameterSpec.getIV()));
return ivParameterSpec;
}
public static byte[] encrypt(String src, byte[] key) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
IvParameterSpec ivParameterSpec = getIv();
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
return cipherBytes;
}
public static byte[] decrypt(String src, byte[] key) throws Exception {
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
IvParameterSpec ivParameterSpec = getIv();
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
byte[] hexBytes = hexStringToBytes(src);
byte[] plainBytes = cipher.doFinal(hexBytes);
return plainBytes;
}
/**
* 解密
* @param src
* @param keyStr
* @return
* @throws Exception
*/
public static String decryptStr(String src, String keyStr) throws Exception {
byte key[] = keyStr.getBytes("utf-8");
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
IvParameterSpec ivParameterSpec = getIv();
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
byte[] hexBytes = hexStringToBytes(src);
byte[] plainBytes = cipher.doFinal(hexBytes);
return new String(plainBytes,"UTF-8");
}
public static String encrypt(String src, String keyStr) throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException, InvalidAlgorithmParameterException {
byte key[] = keyStr.getBytes("utf-8");
SecretKey secretKey = new SecretKeySpec(key, Algorithm);
IvParameterSpec ivParameterSpec = getIv();
Cipher cipher = Cipher.getInstance(AlgorithmProvider);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
byte[] cipherBytes = cipher.doFinal(src.getBytes(Charset.forName("utf-8")));
return new String(cipherBytes,"UTF-8");
}
public static void main(String args[]){
try {
String passwordMd5 = MD5Util.MD5("123456");
System.out.println("加密后密码:"+passwordMd5);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 将byte转换为16进制字符串
* @param src
* @return
*/
public static String byteToHexString(byte[] src) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xff;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
sb.append("0");
}
sb.append(hv);
}
return sb.toString();
}
/**
* 将16进制字符串装换为byte数组
* @param hexString
* @return
*/
public static byte[] hexStringToBytes(String hexString) {
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] b = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
b[i] = (byte) (charToByte(hexChars[pos]) << 4 | (charToByte(hexChars[pos + 1]))& 0xff);
}
return b;
}
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
/*public static void main(String[] args) {
try {
// byte key[] = generatorKey();
System.out.println("FUjs@17654HGJKKn".length());
// 密钥必须是16的倍数
byte key[] = "FUjs@17654HGJKKn".getBytes("utf-8");//hexStringToBytes("0123456789ABCDEF");
String src = "usersrs=111111?sdfjsalkj=1mlkjklasjdfkls?sss=sdfsjlk1123123123?sdd=453456465432165765432221351567897654132";
System.out.println("密钥:"+byteToHexString(key));
System.out.println("原字符串:"+src);
String enc = byteToHexString(encrypt(src, key));
System.out.println("加密:"+enc);
System.out.println("解密:"+decryptStr(enc, AESUtils.key));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}*/
}
(2):
package com.demo.util;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
/**
* Md5算法加密
*
* @author <a href="mailTo:helen@ibw.cn">Helen</a>
* @time Mar 19, 2013
* @version 1.0
*/
public class MD5Util {
private final static Logger logger = LoggerFactory.getLogger(MD5Util.class);
private final static String APP_KEY="hYHN#1son@16faEV2";
private final static String CHARSET="UTF-8";
/**
* MD5加密算法
*
* @param s
* @return
*/
public final static String MD5(String s) throws NoSuchAlgorithmException {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' };
byte[] btInput = s.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst;
mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
}
/**
* 编码转换
* @param content
* @param charset
* @return
* @throws UnsupportedEncodingException
*/
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
public static String sign(String prestr){
String mysign = DigestUtils.md5Hex(getContentBytes(prestr + APP_KEY, CHARSET));
return mysign;
}
public static String signParams(Map<String,String> params){
try {
if (params != null && params.size()>0){
List<Map.Entry<String, String>> list = new ArrayList(params.entrySet());
Collections.sort(list, new Comparator<Map.Entry<String,String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return o1.getKey().compareTo(o2.getKey());
}
});
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, String> ent:list) {
sb.append(ent.getKey());
sb.append(ent.getValue());
}
logger.info("原字符串:{}",sb.toString());
return sign(sb.toString());
}
}catch (Exception e){
}
return "";
}
public static boolean isSign(HashMap<String,String> params,String sign){
try{
String newSign = signParams(params);
logger.info("原签名:{}",sign);
logger.info("新签名:{}",newSign);
if (Objects.equals(sign,newSign)){
return true;
}
}catch (Exception e){
}
return false;
}
}
(3):
package com.demo.util;
import com.demo.constants.Constants;
import com.demo.exception.TokenException;
import com.demo.factory.ServiceFactory;
import io.jsonwebtoken.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
/**
* token管理器
*/
public class JwtProvider {
private static final Logger logger = LoggerFactory.getLogger(JwtProvider.class);
private static RedisClient redisClient;
static {
redisClient = ServiceFactory.getInstance().createRedisClient();
}
/**
* 生成token并将token写入redis
* @param res
* @param username
* @return
*/
public static String addAuthentication(HttpServletResponse res, String username){
String jwtStr = Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + Constants.EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS512, Constants.SECRET)
.compact();
String tokent = jwtStr;
res.addHeader(Constants.HEADER_STRING,tokent );
//每次重置token,实现单一点登录
redisClient.set(Constants.TOKEN_JWT+username,tokent);
return tokent;
}
/**
* 从token中获取username
* @param req
* @return
*/
public static String getAuthentication(HttpServletRequest req){
String token = req.getHeader(Constants.HEADER_STRING);
String username = null;
if(!StringUtils.isEmpty(token)){
try{
// parse the jwt
username = Jwts.parser()
.setSigningKey(Constants.SECRET)
.parseClaimsJws(token)
.getBody()
.getSubject();
}catch (ExpiredJwtException e) {
logger.error("Token已过期: {} " + e);
throw new TokenException("Token已过期");
} catch (UnsupportedJwtException e) {
logger.error("Token格式错误: {} " + e);
throw new TokenException("Token格式错误");
} catch (MalformedJwtException e) {
logger.error("Token没有被正确构造: {} " + e);
throw new TokenException("Token没有被正确构造");
} catch (SignatureException e) {
logger.error("签名失败: {} " + e);
throw new TokenException("签名失败");
} catch (IllegalArgumentException e) {
logger.error("非法参数异常: {} " + e);
throw new TokenException("非法参数异常");
}
}
return username;
}
}
(4):
package com.demo.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.*;
@Component
public class RedisClient {
private final Logger logger = LoggerFactory.getLogger(RedisClient.class);
private final String SUCCESS_OK = "OK";
private final Long SUCCESS_STATUS_LONG = 1L;
// SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作
private final String SET_IF_NOT_EXIST = "NX";
// 给key加一个过期的设置,具体时间由第五个参数决定
private final String SET_WITH_EXPIRE_TIME = "PX";
private static JedisPool jedisPool;
private static final String IP = "127.0.0.1"; // ip
private static final int PORT = 6379; // 端口
// private static final String AUTH=""; // 密码(原始默认是没有密码)
private static int MAX_ACTIVE = 1024; // 最大连接数
private static int MAX_IDLE = 200; // 设置最大空闲数
private static int MAX_WAIT = 10000; // 最大连接时间
private static int TIMEOUT = 10000; // 超时时间
private static boolean BORROW = true; // 在borrow一个事例时是否提前进行validate操作
/**
* 初始化线程池
*/
static {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(MAX_ACTIVE);
config.setMaxIdle(MAX_IDLE);
config.setMaxWaitMillis(MAX_WAIT);
config.setTestOnBorrow(BORROW);
jedisPool = new JedisPool(config, IP, PORT, TIMEOUT);
}
public JedisPool getJedisPool(){
return jedisPool;
}
/**
* 字符串set
*
* @param key
* @param value
* @return
*/
public boolean set(String key, String value) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
String status = jedis.set(key, value);
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis set 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 字符串set
*
* @param key
* @param value
* @param seconds
* 单位秒,大于0
* @return
*/
public boolean set(String key, String value, int seconds) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
String status = jedis.setex(key, seconds, value);
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis set 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
public boolean set(byte[] key, int seconds, byte[] value) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
String status = jedis.setex(key, seconds, value);
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis set 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 是否存在key
*
* @param key
* @return
*/
public boolean isExists(String key) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
return jedis.exists(key);
} catch (Exception e) {
logger.error("redis isExists 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 字符串 删除
*
* @param key
* @return
*/
public boolean del(byte[] key) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
Long status = jedis.del(key);
if (Objects.equals(SUCCESS_STATUS_LONG,status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis del 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
public boolean del(String key) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
Long status = jedis.del(key);
if (Objects.equals(SUCCESS_STATUS_LONG,status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis del 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 字符串获取
*
* @param key
* @return
*/
public String get(String key) {
String ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
ret = jedis.get(key);
} catch (Exception e) {
logger.error("redis get 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
public Long ttl(String key){
Long ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
ret = jedis.ttl(key);
} catch (Exception e) {
logger.error("redis get 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
public byte[] get(byte[] key) {
byte[] ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
ret = jedis.get(key);
} catch (Exception e) {
logger.error("redis get 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 获取分布式锁
*
* @param lockKey
* key为锁
* @param requestId
* 加锁请求
* @param expireTime
* key的过期时间
* @return
*/
public boolean getLock(String lockKey, String requestId, int expireTime) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
String status = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis 获取分布式锁 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 释放分布式锁
*
* @param lockKey
* @param requestId
*/
public boolean releaseLock(String lockKey, String requestId) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
/*
* 其他请求误解锁问题 if(requestId.equals(jedis.get(lockKey))) { jedis.del(lockKey); }
*/
String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
Object status = jedis.eval(script, Collections.singletonList(lockKey),
Collections.singletonList(requestId));
if (SUCCESS_STATUS_LONG.equals(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis 释放分布式锁 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 序列化存入对象
*
* @param key
* @param obj
* @return
*/
public boolean set(byte[] key, Object obj) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
String status = jedis.set(key, baos.toByteArray());
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis set 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 取序列化对象
*
* @param key
* @return
*/
public Object getObj(byte[] key) {
Object ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
byte[] rets = jedis.get(key);
ByteArrayInputStream bais = new ByteArrayInputStream(rets);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
logger.error("redis get 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* hash数据类型存储对象
*
* @param key
* @param obj
* @return
*/
public boolean setHm(String key, Object obj) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
Map<String, String> hash = objToMap(obj);
String status = jedis.hmset(key, hash);
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis setHm 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 修改对象属性
*
* @param key
* @param field
* @param value
* @return
*/
public boolean setHm(String key, String field, String value) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
Long status = jedis.hset(key, field, value);
if (0L == status) {
ret = true;
}
} catch (Exception e) {
logger.error("redis setHm 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 根据fields 查询key对象属性列表
*
* @param key
* @param fields
* @return
*/
public List<String> getHm(String key, String... fields) {
List<String> ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return null;
}
ret = jedis.hmget(key, fields);
} catch (Exception e) {
logger.error("redis getHm 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* 根据field 查询key对象属性
*
* @param key
* @param
* @return
*/
public String getHm(String key, String field) {
String ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return null;
}
ret = jedis.hget(key, field);
} catch (Exception e) {
logger.error("redis getHm 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* json格式存对象
* @param key
* @param obj
* @return
*/
public boolean setJson(String key,Object obj) {
boolean ret = false;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
ObjectMapper mapper = new ObjectMapper();
String status = jedis.set(key, mapper.writeValueAsString(obj));
if (SUCCESS_OK.equalsIgnoreCase(status)) {
ret = true;
}
} catch (Exception e) {
logger.error("redis setJson 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
/**
* json格式取对象
* @param key
* @param clazz
* @return
*/
public Object getJson(String key,Class clazz) {
Object ret = null;
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
if (jedis == null) {
return ret;
}
String str = jedis.get(key);
ObjectMapper mapper = new ObjectMapper();
ret = mapper.readValue(str, clazz);
} catch (Exception e) {
logger.error("redis getJson 出错", e);
jedisPool.returnBrokenResource(jedis);
} finally {
if (null != jedis) {
jedisPool.returnResource(jedis);
}
}
return ret;
}
private HashMap<String, String> objToMap(Object obj) {
if(null == obj) {
return null;
}
HashMap<String, String> map = new HashMap<String, String>();
Field[] fields = obj.getClass().getDeclaredFields();
try {
for (int i = 0; i < fields.length; i++) {
String varName = fields[i].getName();
boolean accessFlag = fields[i].isAccessible();
fields[i].setAccessible(true);
Object o = fields[i].get(obj);
if (o != null) {
map.put(varName, o.toString());
}
fields[i].setAccessible(accessFlag);
}
} catch (Exception e) {
}
return map;
}
/**
* 设置一个key的过期的秒数
*
* @param keyFormat
* key标识
* @param seconds
* 过期的秒数
* @param keyValues
* key变量
* @return 1表示设置成功, 0 表示设置失败或者无法被设置
*/
public Long expire(String key, int seconds) {
Jedis jedis = null;
try {
jedis =jedisPool.getResource();
return jedis.expire(key, seconds);
} finally {
if (jedis != null) {
jedis.close();
}
}
}
}
12、启动类:
package com.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("classpath:consumer.xml")
public class RestStart {
public static void main(String args[]){
SpringApplication.run(RestStart.class,args);
}
}