java jwt框架_Spring安全框架——jwt的集成(服务器端)

新建用户表——users,并完成数据库增删查改

一、新建表

5565f8e1da6a845761e473d3abfdb6a8.png

二、持久化映射,建立模型类,添加主键生成器

//指定生成器名称

@GeneratedValue(generator = "uuid2" )

@GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator" )

三、建立Dao层

package edu.ynmd.cms.dao;

import edu.ynmd.cms.model.Users;

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.Query;

import org.springframework.data.repository.query.Param;

import javax.websocket.server.PathParam;

import java.util.List;

public interface UsersDao extends JpaRepository {

@Query("select u from Users u where u.username=:username and u.pass=:pass")

List getUsersByUsernameAndPass(@Param("username")String username, @Param("pass") String pass);

}

四、配置service层

在ManageService添加方法

//用户表

Users saveUser(Users users);

boolean deleteUser(String id);

Users getUser(String id);

Users getUserByUserNameAndPass(String username,String pass);

在ManageServiceImpl添加方法具体实现

//*****************************用户表增删查改开始*********************************

@Override

public Users saveUser(Users users) {

try {

return usersDao.save(users);

} catch (Exception e) {

e.printStackTrace();

return null;

}

}

@Override

public boolean deleteUser(String id) {

try {

usersDao.deleteById(id);

return true;

} catch (Exception e) {

e.printStackTrace();

}

return false;

}

@Override

public Users getUser(String id) {

Optional temp=usersDao.findById(id);

return temp.isPresent()?temp.get():null;

}

@Override

public Users getUserByUserNameAndPass(String username, String pass) {

List ul=usersDao.getUsersByUsernameAndPass(username,pass);

if(ul.size()>0){

return ul.get(0);

}

return null;

}

JWT框架的搭建

一、添加Maven依赖

org.springframework.boot

spring-boot-starter-security

io.jsonwebtoken

jjwt

0.7.0

二、编写JwtUtil工具类(生成token,解析token,校验token)

package edu.ynmd.cms.tools;

import io.jsonwebtoken.Jwts;

import io.jsonwebtoken.SignatureAlgorithm;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;

public class JwtUtil {

private static final Logger logger= LoggerFactory.getLogger(JwtUtil.class);

public static final long EXPIRATION_TIME=60*60*1000;// 令牌环有效期

public static final String SECRET="abc123456def";//令牌环密钥

public static final String TOKEN_PREFIX="Bearer";//令牌环头标识

public static final String HEADER_STRING="Passport";//配置令牌环在http heads中的键值

public static final String ROLE="ROLE";//自定义字段-角色字段

//生成令牌环

public static String generateToken(String userRole,String userid){

HashMap map=new HashMap<>();

map.put(ROLE,userRole);

map.put("userid",userid);

String jwt= Jwts.builder()

.setClaims(map)

.setExpiration(new Date(System.currentTimeMillis()+EXPIRATION_TIME))

.signWith(SignatureAlgorithm.HS512,SECRET)

.compact();

return TOKEN_PREFIX+" "+jwt;

}

//生成令牌环

public static String generateToken(String userRole,String userid,long exprationtime){

HashMap map=new HashMap<>();

map.put(ROLE,userRole);

map.put("userid",userid);

String jwt= Jwts.builder()

.setClaims(map)

.setExpiration(new Date(System.currentTimeMillis()+exprationtime))

.signWith(SignatureAlgorithm.HS512,SECRET)

.compact();

return TOKEN_PREFIX+" "+jwt;

}

//令牌环校验

public static Map validateTokenAndGetClaims(HttpServletRequest request){

String token=request.getHeader(HEADER_STRING);

if(token==null){

throw new TokenValidationException("Missing Token");

}

else{

Map body=Jwts.parser()

.setSigningKey(SECRET)

.parseClaimsJws(token.replace(TOKEN_PREFIX,""))

.getBody();

return body;

}

}

static class TokenValidationException extends RuntimeException{

public TokenValidationException(String msg){

super(msg);

}

}

}

三、集成JWT filter(拦截器/过滤器)——建立filter包

package edu.ynmd.cms.filter;

import edu.ynmd.cms.tools.JwtUtil;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.util.AntPathMatcher;

import org.springframework.util.PathMatcher;

import org.springframework.web.filter.OncePerRequestFilter;

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.Arrays;

import java.util.Map;

import static edu.ynmd.cms.tools.JwtUtil.ROLE;

public class JwtAuthenticationFilter extends OncePerRequestFilter {

private static final PathMatcher pathmatcher = new AntPathMatcher();

private String[] protectUrlPattern = {"/manage/**", "/member/**", "/auth/**"}; //那些请求需要进行安全校验

public JwtAuthenticationFilter() {

}

@Override

protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

//是不是可以在这里做多种方式登录呢

try {

if (isProtectedUrl(httpServletRequest)) {

Map claims = JwtUtil.validateTokenAndGetClaims(httpServletRequest);

String role = String.valueOf(claims.get(ROLE));

String userid = String.valueOf(claims.get("userid"));

//最关键的部分就是这里, 我们直接注入了

SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(

userid, null, Arrays.asList(() -> role)

));

}

} catch (Exception e) {

e.printStackTrace();

httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());

return;

}

filterChain.doFilter(httpServletRequest, httpServletResponse);

}

//是否是保护连接

private boolean isProtectedUrl(HttpServletRequest request) {

boolean flag = false;

for (int i = 0; i < protectUrlPattern.length; i++) {

if (pathmatcher.match(protectUrlPattern[i], request.getServletPath())) {

return true;

}

}

return false;

}

}

四、配置JWT config类

package edu.ynmd.cms.config;

import edu.ynmd.cms.filter.JwtAuthenticationFilter;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.http.HttpMethod;

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.configuration.EnableWebSecurity;

import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import org.springframework.security.config.http.SessionCreationPolicy;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import org.springframework.security.crypto.password.PasswordEncoder;

import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Bean

public PasswordEncoder passwordEncoder(){

return new BCryptPasswordEncoder();

}

@Override

protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable()

.cors() //允许跨域访问

.and()

.authorizeRequests()

.antMatchers("/").authenticated() //配置那些url需要进行校验--所有请求都需要校验"/"

.antMatchers("/public/**").permitAll() //那些请求不需要校验

.anyRequest().authenticated() //自定义校验类

.and()

.addFilterBefore(new JwtAuthenticationFilter(),

UsernamePasswordAuthenticationFilter.class)

.sessionManagement()

.sessionCreationPolicy(SessionCreationPolicy.STATELESS)//关闭session

;

}

}

五、添加Action注解——在AdminAction添加

@CrossOrigin

@RestController

@PreAuthorize("hasAuthority('admin')") //配置角色,拥有该角色的用户方可访问

@RequestMapping("/manage")

六、登录Action——在PublicAction添加

//用户登录方法

@PostMapping("/login")

@ResponseBody

public HashMap login(

@RequestBody Account account) throws IOException {

Users u=manageService.getUserByUserNameAndPass(account.username,account.password);

//if(account.username.equals("admin")&&account.password.equals("123456")){

if(u!=null){

//String jwt= JwtUtil.generateToken("admin","123456789abc");

String jwt= JwtUtil.generateToken(u.getRoleid(),u.getUsersid());

return new HashMap(){{

put("msg","ok");

put("token",jwt);

put("role",u.getRoleid());

// put("role","admin");

}};

}

else {

//return new ResponseEntity(HttpStatus.UNAUTHORIZED);

return new HashMap(){{

put("msg","error");

put("token","error");

}};

}

}

public static class Account{

public String username;

public String password;

}

七、token令牌环,访问需要验证的资源,新建service工具类

在tools中添加isNullOrSpace方法进行判断

public static boolean isNullOrSpace(String value){

if(value==null){

return true;

}

else {

if(value.equals("")){

return true;

}

else {

return false;

}

}

}

在ManageService添加方法

String getCurrentUserId();

String getCurrentRole();

在ManageServiceImpl添加方法具体实现

//获取当前登录用的的Id

@Override

public String getCurrentUserId() {

String userid= (String) SecurityContextHolder.getContext().getAuthentication() .getPrincipal();

if(Tools.isNullOrSpace(userid)){

return null;

}

else {

return userid;

}

}

//获取当前登录用户的角色

@Override

public String getCurrentRole() {

String role=null;

Collection authorities = (Collection) SecurityContextHolder.getContext().getAuthentication().getAuthorities();

for (GrantedAuthority authority : authorities) {

role = authority.getAuthority();

}

if(Tools.isNullOrSpace(role)){

return null;

}

else{

return role;

}

}

八、识别token令牌环信息——在AdminAction添加

@GetMapping("testSecurityResource")

@ResponseBody

public String testSecurityResource() throws Exception{

String userid=manageService.getCurrentUserId();

String role=manageService.getCurrentRole();

return "受保护的资源,当前用户的id是"+userid+"当前用户的角色是"+role;

}

九、自动更新令牌环,新建AuthAction类

package edu.ynmd.cms.action;

import edu.ynmd.cms.tools.JwtUtil;

import edu.ynmd.cms.tools.Tools;

import org.springframework.security.access.prepost.PreAuthorize;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.SimpleGrantedAuthority;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

import java.util.Collection;

import java.util.HashMap;

//令牌环更新

@CrossOrigin

@RestController

@PreAuthorize("hasAuthority('admin')")

@RequestMapping("/auth")

public class AuthAction {

//更新令牌环信息

@GetMapping("refreshToken")

@ResponseBody

public HashMap refreshToken( HttpServletRequest request){

String role=null;

Collection authorities = (Collection) SecurityContextHolder.getContext().getAuthentication().getAuthorities();

for (GrantedAuthority authority : authorities) {

role = authority.getAuthority();

}

// UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication() .getPrincipal();

String userid= (String)SecurityContextHolder.getContext().getAuthentication() .getPrincipal();

if(Tools.isNullOrSpace(role)){

return new HashMap(){{

put("token","error");

}};

}

else{

String jwt="";

jwt= JwtUtil.generateToken(role,userid,60*60*1000);//一小时

HashMap m=new HashMap<>();

m.put("token",jwt);

return m;

}

}

//获取当前登录用户的角色

@GetMapping("getRole")

@ResponseBody

public HashMap getRoleByToken(){

String role="";

String userid="";

Collection authorities = (Collection) SecurityContextHolder.getContext().getAuthentication().getAuthorities();

for (GrantedAuthority authority : authorities) {

role = authority.getAuthority();

}

if(Tools.isNullOrSpace(role)){

return new HashMap(){{

put("role","error");

}};

}

else{

HashMap m=new HashMap<>();

m.put("role",role);

return m;

}

}

}

最后用postman进行测试

6ed18f49ca569c8daa6bf3b024910e93.png

结果

e1aa7f062ecdf14c4a472fe41d88374b.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值