Spring rest 配置jwt 安全验证

本文介绍了如何在Spring Security框架中使用JSON Web Tokens (JWT) 替换基本身份验证。详细解释了JWT的工作原理,包括JWS签名的重要性,并提供了配置示例及自定义JWT过滤器和提供者的代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在用spring + mybatis 做项目。之前安全验证用basic 方式现在想换成jwt。

jwt :

JWS模式对这个内容进行了数字化签名。这个内容被用来存放JWT的声明.服务端签名出JWT并且发送到客户端,并在用户成功认证后进行应答。服务器期望客户端在下次请求的时候将JWS作为请求的一部分,发送回服务端。

  如果我们处理的客户端是欺骗者则么办?这就是签名(signature)需要出场的地方了。签名携带了完整的可验证的信息。换句话说,服务器可以确认,接收到的JWT声明里的JWS是没有经过欺骗客户端、中间者进行修改的。

  服务端通过验证消息的签名来确保客户端没有修改声明。如果服务端检测到任何修改,可以采取适当的动作(拒绝这次请求或者锁定客户端之类的)

  客户端同样可以验证签名,为了做到这点,客户端也需要服务端的secret(密钥)(如果这个JWT签名是HMAC算法),或者需要服务端对公钥(如果这个WJT是数字化签名)

  特别注意:对于JWS,荷载(声明部分)没有进行加密,所以,不要发送任何敏感信息.

 

 

首先在web.xml 中

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/spring-mybatis.xml
			/WEB-INF/spring-security.xml
			classpath:applicationContext.xml
		</param-value>
	</context-param>



	<!-- Security -->
	<filter>
		<filter-name>springSecurityFilterChain</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
	</filter>

	<filter-mapping>
		<filter-name>springSecurityFilterChain</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>


	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>


	<servlet>
		<servlet-name>fly.fky</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>fly.fky</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>

	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
</web-app>

 

spring-sucurity.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context   
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd">
	<context:annotation-config />
	<global-method-security pre-post-annotations="enabled" />
	<beans:bean id="passwordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder">
		<beans:constructor-arg value="ThisIsASecretSoChangeMe" />
	</beans:bean>
	<!-- 
	<authentication-manager id="authenticationManager"
		erase-credentials="false">
		<authentication-provider user-service-ref="userService">
			<password-encoder ref="passwordEncoder"></password-encoder>
		</authentication-provider>
	</authentication-manager>
	<http pattern="/**" entry-point-ref="unauthorizedEntryPoint"
		create-session="stateless">
		<csrf disabled="true" />
		<custom-filter before="FORM_LOGIN_FILTER" ref="jwtAuthenticationFilter" />
	</http>


	<beans:bean id="jwtAuthenticationFilter"
		class="fly.fky.restapi.security.JwtAuthenticationFilter">
		<beans:property name="authenticationManager" ref="authenticationManager" />
		<beans:property name="authenticationSuccessHandler"
			ref="jwtAuthenticationSuccessHandler" />
	</beans:bean>

	<beans:bean id="unauthorizedEntryPoint"
		class="fly.fky.restapi.service.UnauthorizedEntryPoint" />


	<beans:bean id="jwtAuthenticationSuccessHandler"
		class="fly.fky.restapi.security.JwtAuthenticationSuccessHandler" />


	<!-- authentication manager -->

	<authentication-manager id="authenticationManager">
		<authentication-provider ref="jwtAuthenticationProvider">
		</authentication-provider>
	</authentication-manager>

	<beans:bean id="jwtAuthenticationProvider"
		class="fly.fky.restapi.security.JwtAuthenticationProvider" />
</beans:beans>

 

jwt filter 文件

public class JwtAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

	public JwtAuthenticationFilter() {
		super("/**");
	}

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws AuthenticationException, IOException, ServletException {
		String header = request.getHeader("Authorization");

        if (header == null || !header.startsWith("Bearer ")) {
        	throw new RestAPIAuthenticationException(MessageToClientFormat.formateMsg("No JWT token found in request headers"));
        }

        String authToken = header.substring(7);

       return JwtTokenUtil.getAuthentication(authToken);
	}

}

JwtAuthenticationProvider


public class JwtAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {

	@Resource
	private UserService userService;
	
	
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
		
		if (authentication.getCredentials() == null) {
			logger.debug("Authentication failed: no credentials provided");

			throw new BadCredentialsException(messages.getMessage(
					"AbstractUserDetailsAuthenticationProvider.badCredentials",
					"Bad credentials"));
		}
		
		String presentedPassword = authentication.getCredentials().toString();

		if (!userService.isPasswordMatched(presentedPassword, userDetails.getPassword())) {
			logger.debug("Authentication failed: password does not match stored value");

			throw new BadCredentialsException(messages.getMessage(
					"AbstractUserDetailsAuthenticationProvider.badCredentials",
					"Bad credentials"));
		}
	}

	@Override
	protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		return userService.loadUserByUsername(username);
		
	}

}

 

转载于:https://my.oschina.net/u/241688/blog/1557542

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值