shiro登陆失败提示_shiro 无状态权限认证

shiro 无状态权限认证

2bb702aba648e94777d0f9ae67339cbb.png
pom
 <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 ​
 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <scope>runtime</scope>
 </dependency>
 ​
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.3.2</version>
 </dependency>
 ​
 <dependency>
     <groupId>org.apache.shiro</groupId>
     <artifactId>shiro-spring</artifactId>
     <version>1.4.0</version>
 </dependency>
 ​
 <!--druid-->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.1.21</version>
 </dependency>
 <!--jwt-->
 <dependency>
     <groupId>javax.xml.bind</groupId>
     <artifactId>jaxb-api</artifactId>
 </dependency>
 <dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt</artifactId>
     <version>0.9.0</version>
     <scope>compile</scope>
 </dependency>
 <!--json-->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.68</version>
 </dependency>
禁用session生成
 /**
  * @author spp
  * @date 2020-06-13 17:35
  **/
 public class StatelessDefaultSubjectFactory extends DefaultWebSubjectFactory {
     @Override
     public Subject createSubject(SubjectContext context) {
         //禁用生成session
         context.setSessionCreationEnabled(false);
         return super.createSubject(context);
     }
 }
shiro配置类
 /**
  * @author spp
  * @date 2020-06-13 17:13
  **/
 @Configuration
 public class ShiroConfig {
     //ShiroFilterFactoryBean
     @Bean
     public ShiroFilterFactoryBean getFactory(@Autowired DefaultWebSecurityManager manager){
         ShiroFilterFactoryBean factory = new ShiroFilterFactoryBean();
         //设置安全管理器
 ​
         //添加shiro的内置过滤器
         /*
             anon:无需认证就可以访问
             authc:必须认证了才能访问
             user: 必须 设置 记住我才能访问
             perms: 拥有对某个资源的权限才能登陆
             role: 拥有某个角色权限才能访问
          */
         factory.setSecurityManager(manager);
         factory.getFilters().put("jwt",new JwtFilter());
         Map<String,String> filterMap = new LinkedHashMap<>();
         //filterMap.put("/login","anon");
         filterMap.put("/**","jwt");
         factory.setFilterChainDefinitionMap(filterMap);
         factory.setLoginUrl("/login");
         factory.setUnauthorizedUrl("/unauthorized");
         return factory;
     }
 ​
     @Bean
     @Autowired
     public DefaultWebSecurityManager getManager(MyRealm realm){
         DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
         
         DefaultSessionManager defaultSessionManager = new DefaultSessionManager ();
         defaultSessionManager.setSessionValidationSchedulerEnabled(false);
         //禁用session
         manager.setSubjectFactory(new StatelessDefaultSubjectFactory());
 ​
         manager.setSessionManager(defaultSessionManager);
         // 禁用Session作为存储策略的实现。
         DefaultSubjectDAO defaultSubjectDAO = (DefaultSubjectDAO) manager.getSubjectDAO();
         DefaultSessionStorageEvaluator defaultSessionStorageEvaluatord = (DefaultSessionStorageEvaluator) defaultSubjectDAO
                 .getSessionStorageEvaluator();
         defaultSessionStorageEvaluatord.setSessionStorageEnabled(false);
         manager.setRealm(realm);
         return manager;
     }
 ​
 }
自定义的jwt过滤器,继承BasicHttpAuthenticationFilter
 /**
  * @author spp
  * @date 2020-06-13 17:31
  **/
 @Slf4j
 public class JwtFilter extends BasicHttpAuthenticationFilter {
     private static final String LOGIN = "/login";
     private static final String SECRET_KEY = "auth_sp";
     @Override
     protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
         log.info("isAccessAllowed");
         HttpServletRequest r = (HttpServletRequest) request;
         if (LOGIN.equals(r.getRequestURI())){
             return true;
         }
         String token = r.getHeader(SECRET_KEY);
         try {
             Boolean expired = JwtTokenUtil.isTokenExpired(token);
             if (!expired){
                 User u = JwtTokenUtil.getUsernameFromToken(token);
                 log.info(u.toString() + "--->进行jwt认证");
                 return true;
             }
             return false;
         } catch (Exception e) {
             request.setAttribute("error",e.getMessage());
             return false;
         }
     }
     
     //认证失败
     @Override
     protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
         response.setContentType("application/json;charset=utf8");
         Object error = request.getAttribute("error");
         if(!ObjectUtils.isEmpty(error)){
             response.getWriter().println(error);
             return false;
         }
         response.getWriter().println("error");
         return false;
     }
 }
jwt工具类
 /**
  * JWT生成令牌、验证令牌、获取令牌
  * @author 76986
  */
 @Component
 @NoArgsConstructor
 public class JwtTokenUtil {
 ​
     /**
      * 私钥
      */
     private static final String SECRET_KEY = "auth_sp";
 ​
     /**
      * 过期时间 毫秒,设置默认两小时过期
      */
     private static final long EXPIRATION_TIME = 3600000L * 2;
 ​
     /**
      * 生成令牌
      * @param user 用户
      * @return 令牌
      */
     public static String generateToken(User user) {
         Map<String, Object> claims = new HashMap<>(2);
         claims.put(Claims.SUBJECT,user);
         claims.put(Claims.ISSUED_AT, new Date());
         return generateToken(claims);
     }
 ​
     /**
      * 从令牌中获取用户
      * @param token 令牌
      * @return 用户名
      */
     public static User getUsernameFromToken(String token) {
         User user = new User();
         try {
             Claims claims = getClaimsFromToken(token);
             String subject = claims.getSubject();
             subject = subject.replace("{","").replace("}","");
             String[] split = subject.split(",");
             user.setUsername(split[0].split("=")[1]);
             user.setPassword(split[1].split("=")[1]);
             System.out.println(user);
         } catch (Exception e) {
             System.out.println("e = " + e.getMessage());
         }
         return user;
     }
 ​
     /**
      * 判断令牌是否过期
      *
      * @param token 令牌
      * @return 是否过期
      */
     public static Boolean isTokenExpired(String token) throws  Exception{
         try {
             Claims claims = getClaimsFromToken(token);
             Date expiration = claims.getExpiration();
             return expiration.before(new Date());
         } catch (Exception e) {
            throw new Exception("签名过期或者token不正确");
         }
     }
 ​
     /**
      * 刷新令牌
      *
      * @param token 原令牌
      * @return 新令牌
      */
     public static String refreshToken(String token) {
         String refreshedToken;
         try {
             Claims claims = getClaimsFromToken(token);
             claims.put(Claims.ISSUED_AT, new Date());
             refreshedToken = generateToken(claims);
         } catch (Exception e) {
             refreshedToken = null;
         }
         return refreshedToken;
     }
 ​
 ​
     /**
      * 从数据声明生成令牌
      *
      * @param claims 数据声明
      * @return 令牌
      */
     private static String generateToken(Map<String, Object> claims) {
         Date expirationDate = new Date(System.currentTimeMillis()+ EXPIRATION_TIME);
         HashMap<String, Object> map = new HashMap<>(1);map.put("typ",Header.JWT_TYPE);
         return Jwts.builder().setHeader(map).setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, SECRET_KEY).compact();
     }
 ​
     /**
      * 从令牌中获取数据声明
      *
      * @param token 令牌
      * @return 数据声明
      */
     private static Claims getClaimsFromToken(String token) throws Exception {
         Claims claims = null;
         try {
             claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
         } catch (Exception e) {
             new Throwable(e);
         }
         return claims;
     }
 }
登陆控制器
 /**
  * @author spp
  * @date 2020-06-13 18:23
  **/
 @RestController
 public class Index {
     private Logger logger = LoggerFactory.getLogger(Index.class);
     @GetMapping("/login")
     public R login(User user){
         UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
         try {
             SecurityUtils.getSubject().login(token);
         }catch (IncorrectCredentialsException e){
             return new R(ApiErrorCode.FAILED).setMsg(e.getMessage());
         }
         String s = JwtTokenUtil.generateToken(user);
         logger.info(s);
         return new R(ApiErrorCode.SUCCESS).setMsg("登陆成功");
     }
 }
自定义登陆处理类
 /**
  * @author 76986
  */
 @Component
 public class MyRealm extends AuthorizingRealm {
 ​
     /**
      * 授权
      * @param principalCollection
      * @return
      */
     @Override
     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
         return null;
     }
 ​
     /**
      * 登陆
      * @param authenticationToken
      * @return
      * @throws AuthenticationException
      */
     @Override
     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
         UsernamePasswordToken tok = (UsernamePasswordToken) authenticationToken;
         User user = new User("admin","123456");
         return new SimpleAuthenticationInfo(user, user.getPassword(),getName());
     }
 }
测试

先登陆拿token

a3a703b309fba7fc9b83b6fcadc1c20f.png

携带token访问,正常

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值